From 70c87dd1ab14272813bc318959111557ead99d5f Mon Sep 17 00:00:00 2001 From: tuchida Date: Wed, 27 Jan 2021 08:56:07 +0900 Subject: [PATCH] Fixed a broken StackMapTable. --- .../mozilla/classfile/ClassFileWriter.java | 8 ++- .../classfile/tests/ClassFileWriterTest.java | 61 +++++++++++++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 testsrc/org/mozilla/classfile/tests/ClassFileWriterTest.java diff --git a/src/org/mozilla/classfile/ClassFileWriter.java b/src/org/mozilla/classfile/ClassFileWriter.java index e54498dc21..929f7a0c86 100644 --- a/src/org/mozilla/classfile/ClassFileWriter.java +++ b/src/org/mozilla/classfile/ClassFileWriter.java @@ -2176,8 +2176,12 @@ private int execute(int bci) { if (tag == TypeInfo.UNINITIALIZED_VARIABLE(0) || tag == TypeInfo.UNINITIALIZED_THIS) { if ("".equals(methodName)) { - int newType = - TypeInfo.OBJECT(itsThisClassIndex); + int newType; + if (tag == TypeInfo.UNINITIALIZED_VARIABLE(0)) { + newType = TypeInfo.OBJECT(m.getClassName(), itsConstantPool); + } else { + newType = TypeInfo.OBJECT(itsThisClassIndex); + } initializeTypeInfo(instType, newType); } else { throw new IllegalStateException("bad instance"); diff --git a/testsrc/org/mozilla/classfile/tests/ClassFileWriterTest.java b/testsrc/org/mozilla/classfile/tests/ClassFileWriterTest.java new file mode 100644 index 0000000000..014e783de8 --- /dev/null +++ b/testsrc/org/mozilla/classfile/tests/ClassFileWriterTest.java @@ -0,0 +1,61 @@ +package org.mozilla.javascript.classfile.tests; + +import java.lang.reflect.Method; +import java.math.BigInteger; + +import org.junit.Test; +import org.mozilla.classfile.ByteCode; +import org.mozilla.classfile.ClassFileWriter; +import org.mozilla.javascript.DefiningClassLoader; +import static org.mozilla.classfile.ClassFileWriter.ACC_PUBLIC; +import static org.mozilla.classfile.ClassFileWriter.ACC_STATIC; + +import static org.junit.Assert.*; + +public class ClassFileWriterTest { + @Test + public void testStackMapTable() throws Exception { + final String CLASS_NAME = "TestStackMapTable"; + final String METHOD_NAME = "returnObject"; + + ClassFileWriter cfw = new ClassFileWriter(CLASS_NAME, + "java/lang/Object", + "ClassFileWriterTest.java");; + + // public static Object returnObject() + cfw.startMethod(METHOD_NAME, "()Ljava/lang/Object;", (short)(ACC_PUBLIC | ACC_STATIC)); + + cfw.add(ByteCode.NEW, "java/math/BigInteger"); + cfw.add(ByteCode.DUP); + + // new byte[]{ 123 } + cfw.addPush(1); + cfw.add(ByteCode.NEWARRAY, ByteCode.T_BYTE); + cfw.add(ByteCode.DUP); + cfw.addPush(0); + cfw.add(ByteCode.BIPUSH, 123); + cfw.add(ByteCode.BASTORE); + + // new java.math.BigInteger(bytes) + cfw.addInvoke(ByteCode.INVOKESPECIAL, "java/math/BigInteger", "", "([B)V"); + + // generate StackMapTable + cfw.add(ByteCode.DUP); + int target = cfw.acquireLabel(); + cfw.add(ByteCode.IFNULL, target); + cfw.markLabel(target); + + cfw.add(ByteCode.ARETURN); + cfw.stopMethod((short)0); + + byte[] bytecode = cfw.toByteArray(); + DefiningClassLoader loader = new DefiningClassLoader(); + Class cl = loader.defineClass(CLASS_NAME, bytecode); + + Method method = cl.getMethod(METHOD_NAME); + Object ret = method.invoke(cl); + + assertTrue(ret instanceof BigInteger); + assertEquals(ret, new BigInteger(new byte[]{ 123 })); + } +}