handling invalid ConstantValue attributes

Jonathan Gibbons jonathan.gibbons at oracle.com
Thu Nov 3 22:35:22 UTC 2016


Well, javac should never give a stacktrace, so any time that it does is 
worthy of a bug report.

-- Jon


On 11/03/2016 03:26 PM, Liam Miller-Cushon wrote:
> javac silently accepts class files containing ConstantValue attributes 
> of the incorrect
> type, or outside of the allowed ranges for int, short, char, byte, and 
> booleans.
>
> I expected javac to either reject the invalid bytecode, or convert the 
> constants to
> their canonical representation (e.g. constant booleans should always 
> be 0 or 1).
>
> ecj rejects constants with the wrong type, and normalizes values 
> outside of the
> expected range.
>
> I couldn't find anything in the spec for this, is it up to the 
> implementation? Would it
> be possible to change javac's behaviour here?
>
> === Dump.java
> import java.nio.file.Files;
> import java.nio.file.Paths;
> import org.objectweb.asm.ClassWriter;
> import org.objectweb.asm.Opcodes;
>
> public class Dump {
>
>   public static void main(String[] args) throws Exception {
>     Files.write(Paths.get("Lib.class"), dump());
>   }
>
>   static byte[] dump() {
>     ClassWriter cw = new ClassWriter(0);
>     cw.visit(52, Opcodes.ACC_SUPER, "Lib", null, "java/lang/Object", 
> null);
>     cw.visitField(
>         Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_PUBLIC, 
> "A", "Z", null, "hello");
>     cw.visitField(
>         Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_PUBLIC, 
> "B", "Z", null, 2);
>     cw.visitEnd();
>     return cw.toByteArray();
>   }
> }
> ===
>
> === Test.java
> class Test {
>   static final boolean ONE = Lib.A;
>   static final boolean TWO = Lib.B;
> }
> ===
>
> === Test2.java
> class Test2 {
>   static final boolean ONE = Lib.A || true;
> }
> ===
>
>
> $ javac -cp asm-debug-all-5.1.jar Dump.java
> $ java -cp asm-debug-all-5.1.jar:. Dump
> $ javac Test.java
> $ javap -v Test
> ...
>   static final boolean ONE;
>     descriptor: Z
>     flags: ACC_STATIC, ACC_FINAL
>     ConstantValue: String hello
>
>   static final boolean TWO;
>     descriptor: Z
>     flags: ACC_STATIC, ACC_FINAL
>     ConstantValue: int 2
>
> $ javac Test2.java
> ...
> java.lang.AssertionError: java.lang.ClassCastException: 
> java.lang.String (in module: java.base) cannot be cast to 
> java.lang.Number (in module: java.base)
> at 
> com.sun.tools.javac.code.Symbol$VarSymbol.getConstValue(jdk.compiler at 9-ea/Symbol.java:1530)
> at 
> com.sun.tools.javac.comp.Attr.visitVarDef(jdk.compiler at 9-ea/Attr.java:1122)
> ...
> Caused by: java.lang.ClassCastException: java.lang.String (in module: 
> java.base) cannot be cast to java.lang.Number (in module: java.base)
> at 
> com.sun.tools.javac.comp.ConstFold.intValue(jdk.compiler at 9-ea/ConstFold.java:71)
> at 
> com.sun.tools.javac.comp.ConstFold.fold2(jdk.compiler at 9-ea/ConstFold.java:187)
> at 
> com.sun.tools.javac.comp.Attr.visitBinary(jdk.compiler at 9-ea/Attr.java:3211)

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20161103/e270eed3/attachment.html>


More information about the compiler-dev mailing list