[ 
https://issues.apache.org/jira/browse/GROOVY-8906?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Curtis Mackie updated GROOVY-8906:
----------------------------------
    Description: 
BigInteger(long) is a privileged constructor that behaves incorrectly for zero. 
When CompileStatic is not used, this constructor is exposed. Thus, the 
following assertion:
{code:java}
assert new BigInteger("0") == new BigInteger(0){code}
fails.
----
BigDecimal(BigInteger, long, int, int) is a privileged constructor that assumes 
well-formed arguments. When CompileStatic is not used, this constructor is 
exposed, allowing for this code:
{code:java}
BigDecimal nullbomb = new BigDecimal(null, Long.MIN_VALUE, 10, 10)
{code}
to produce a seemingly valid BigDecimal, which nevertheless throws a 
NullPointerException when touched.
----
String(char[], boolean) is a privileged constructor that allows memory to be 
shared between two strings. When CompileStatic is not used, this constructor is 
exposed, allowing for the following code:
{code:java}
class EvilStringProvider {
    char[] good = "Good"
    char[] evil = "Evil"

    def getGoodString() {
        new String(good, true)
    }

    def surprise() {
        for (int i = 0; i < good.length; i++) {
            good[i] = evil[i]
        }
    }
}

def provider = new EvilStringProvider()

def myGoodString = provider.goodString
println myGoodString

provider.surprise()
println myGoodString
{code}
An object produces a string that says "Good", but is then magically able to 
change it to say "Evil" later on, violating the immutability assumption of 
Strings.
----
If CompileStatic is active, all three of these examples will either fail due to 
the constructor not being found, or, in the case of BigInteger, the constructor 
argument will be implicitly converted to match a public constructor.

Of course, Java reflection can replicate all of these effects, and many more 
dangerous effects besides. But code that does not appear to contain dangerous 
reflection should not be able to produce such effects.

Side note: I'm not an expert on Groovy source code, but I think 
org.codehaus.groovy.reflection.CachedClass might be the culprit here; it 
appears to expose the constructors of its argument class without considering 
their access level. org.codehaus.groovy.reflection.stdclasses contains a number 
of classes that apply CachedClass to a number of standard library classes, 
including BigInteger, BigDecimal, and String.

  was:
BigInteger(long) is a privileged constructor that behaves incorrectly for zero. 
When CompileStatic is not used, this constructor is exposed. Thus, the 
following assertion:

 
{code:java}
assert new BigInteger("0") == new BigInteger(0){code}
fails.
----
 

BigDecimal(BigInteger, long, int, int) is a privileged constructor that assumes 
well-formed arguments. When CompileStatic is not used, this constructor is 
exposed, allowing for this code:

 
{code:java}
BigDecimal nullbomb = new BigDecimal(null, Long.MIN_VALUE, 10, 10)
{code}
to produce a seemingly valid BigDecimal, which nevertheless throws a 
NullPointerException when touched.
----
String(char[], boolean) is a privileged constructor that allows memory to be 
shared between two strings. When CompileStatic is not used, this constructor is 
exposed, allowing for the following code:

 
{code:java}
class EvilStringProvider {
    char[] good = "Good"
    char[] evil = "Evil"

    def getGoodString() {
        new String(good, true)
    }

    def surprise() {
        for (int i = 0; i < good.length; i++) {
            good[i] = evil[i]
        }
    }
}

def provider = new EvilStringProvider()

def myGoodString = provider.goodString
println myGoodString

provider.surprise()
println myGoodString
{code}
An object produces a string that says "Good", but is then magically able to 
change it to say "Evil" later on, violating the immutability assumption of 
Strings.

 
----
If CompileStatic is active, all three of these examples will either fail due to 
the constructor not being found, or, in the case of BigInteger, the constructor 
argument will be implicitly converted to match a public constructor.

Of course, Java reflection can replicate all of these effects, and many more 
dangerous effects besides. But code that does not appear to contain dangerous 
reflection should not be able to produce such effects.

Side note: I'm not an expert on Groovy source code, but I think 
org.codehaus.groovy.reflection.CachedClass might be the culprit here; it 
appears to expose the constructors of its argument class without considering 
their access level. org.codehaus.groovy.reflection.stdclasses contains a number 
of classes that apply CachedClass to a number of standard library classes, 
including BigInteger, BigDecimal, and String.


> Dynamic compilation exposes privileged constructors
> ---------------------------------------------------
>
>                 Key: GROOVY-8906
>                 URL: https://issues.apache.org/jira/browse/GROOVY-8906
>             Project: Groovy
>          Issue Type: Bug
>          Components: Compiler
>    Affects Versions: 2.5.4
>         Environment: OpenJDK 10
>            Reporter: Curtis Mackie
>            Priority: Major
>
> BigInteger(long) is a privileged constructor that behaves incorrectly for 
> zero. When CompileStatic is not used, this constructor is exposed. Thus, the 
> following assertion:
> {code:java}
> assert new BigInteger("0") == new BigInteger(0){code}
> fails.
> ----
> BigDecimal(BigInteger, long, int, int) is a privileged constructor that 
> assumes well-formed arguments. When CompileStatic is not used, this 
> constructor is exposed, allowing for this code:
> {code:java}
> BigDecimal nullbomb = new BigDecimal(null, Long.MIN_VALUE, 10, 10)
> {code}
> to produce a seemingly valid BigDecimal, which nevertheless throws a 
> NullPointerException when touched.
> ----
> String(char[], boolean) is a privileged constructor that allows memory to be 
> shared between two strings. When CompileStatic is not used, this constructor 
> is exposed, allowing for the following code:
> {code:java}
> class EvilStringProvider {
>     char[] good = "Good"
>     char[] evil = "Evil"
>     def getGoodString() {
>         new String(good, true)
>     }
>     def surprise() {
>         for (int i = 0; i < good.length; i++) {
>             good[i] = evil[i]
>         }
>     }
> }
> def provider = new EvilStringProvider()
> def myGoodString = provider.goodString
> println myGoodString
> provider.surprise()
> println myGoodString
> {code}
> An object produces a string that says "Good", but is then magically able to 
> change it to say "Evil" later on, violating the immutability assumption of 
> Strings.
> ----
> If CompileStatic is active, all three of these examples will either fail due 
> to the constructor not being found, or, in the case of BigInteger, the 
> constructor argument will be implicitly converted to match a public 
> constructor.
> Of course, Java reflection can replicate all of these effects, and many more 
> dangerous effects besides. But code that does not appear to contain dangerous 
> reflection should not be able to produce such effects.
> Side note: I'm not an expert on Groovy source code, but I think 
> org.codehaus.groovy.reflection.CachedClass might be the culprit here; it 
> appears to expose the constructors of its argument class without considering 
> their access level. org.codehaus.groovy.reflection.stdclasses contains a 
> number of classes that apply CachedClass to a number of standard library 
> classes, including BigInteger, BigDecimal, and String.



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to