Affects Version/s: 2.5.4
Fix Version/s: None
BigInteger(long) is a privileged constructor that behaves incorrectly for zero. When CompileStatic is not used, this constructor is exposed. Thus, the following assertion:
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:
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:
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.