Curtis Mackie created GROOVY-8906:
-------------------------------------

             Summary: 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


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