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)