From 90ed7895339b2d61a3ac8ba73aa4383aa9a86b82 Mon Sep 17 00:00:00 2001 From: Jay Arthanareeswaran Date: Mon, 29 Apr 2019 12:50:44 +0530 Subject: Bug 540902 - JRE Verify Error Case: Inconsistent stackmap frames Change-Id: Idbb98d5dfbf676b014637d2d9f13ba7dfd3fb78a Signed-off-by: Jay Arthanareeswaran --- .../compiler/regression/StackMapAttributeTest.java | 117 +++++++++++++++++++++ .../compiler/codegen/StackMapFrameCodeStream.java | 22 +--- 2 files changed, 119 insertions(+), 20 deletions(-) diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java index 5458587d5a..3c1f77b2d8 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java @@ -8603,4 +8603,121 @@ public class StackMapAttributeTest extends AbstractRegressionTest { assertEquals("Wrong contents", expectedOutput, actualOutput); } } + public void testBug5409021() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + "\n" + + " public static void main(String[] args) {\n" + + " X error = new X();\n" + + " error.reproduce(\"hello\");\n" + + " System.out.println(\"DONE\");\n" + + " }\n" + + " \n" + + " public Object reproduce(Object param) throws RuntimeException {\n" + + " Object local;\n" + + " try {\n" + + " return param; \n" + + " } \n" + + " catch (RuntimeException e) {\n" + + " return null;\n" + + " } \n" + + " finally {\n" + + " if (param != null) {\n" + + " System.out.println(\"FINALLY\");\n" + + " }\n" + + " local = null;\n" + + " }\n" + + " }\n" + + "}\n" + + "", + }, + "FINALLY\n" + + "DONE"); + + ClassFileBytesDisassembler disassembler = ToolFactory.createDefaultClassFileBytesDisassembler(); + byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(new File(OUTPUT_DIR + File.separator +"X.class")); + String actualOutput = + disassembler.disassemble( + classFileBytes, + "\n", + ClassFileBytesDisassembler.DETAILED); + String expectedOutput = + " // Stack: 2, Locals: 6\n" + + " public java.lang.Object reproduce(java.lang.Object param) throws java.lang.RuntimeException;\n" + + " 0 aload_1 [param]\n" + + " 1 astore 5\n" + + " 3 aload_1 [param]\n" + + " 4 ifnull 15\n" + + " 7 getstatic java.lang.System.out : java.io.PrintStream [23]\n" + + " 10 ldc [43]\n" + + " 12 invokevirtual java.io.PrintStream.println(java.lang.String) : void [31]\n" + + " 15 aconst_null\n" + + " 16 astore_2 [local]\n" + + " 17 aload 5\n" + + " 19 areturn\n" + + " 20 astore_3 [e]\n" + + " 21 aload_1 [param]\n" + + " 22 ifnull 33\n" + + " 25 getstatic java.lang.System.out : java.io.PrintStream [23]\n" + + " 28 ldc [43]\n" + + " 30 invokevirtual java.io.PrintStream.println(java.lang.String) : void [31]\n" + + " 33 aconst_null\n" + + " 34 astore_2 [local]\n" + + " 35 aconst_null\n" + + " 36 areturn\n" + + " 37 astore 4\n" + + " 39 aload_1 [param]\n" + + " 40 ifnull 51\n" + + " 43 getstatic java.lang.System.out : java.io.PrintStream [23]\n" + + " 46 ldc [43]\n" + + " 48 invokevirtual java.io.PrintStream.println(java.lang.String) : void [31]\n" + + " 51 aconst_null\n" + + " 52 astore_2 [local]\n" + + " 53 aload 4\n" + + " 55 athrow\n" + + " Exception Table:\n" + + " [pc: 0, pc: 3] -> 20 when : java.lang.RuntimeException\n" + + " [pc: 0, pc: 3] -> 37 when : any\n" + + " [pc: 20, pc: 21] -> 37 when : any\n" + + " Line numbers:\n" + + " [pc: 0, line: 12]\n" + + " [pc: 3, line: 18]\n" + + " [pc: 7, line: 19]\n" + + " [pc: 15, line: 21]\n" + + " [pc: 17, line: 12]\n" + + " [pc: 20, line: 14]\n" + + " [pc: 21, line: 18]\n" + + " [pc: 25, line: 19]\n" + + " [pc: 33, line: 21]\n" + + " [pc: 35, line: 15]\n" + + " [pc: 37, line: 17]\n" + + " [pc: 39, line: 18]\n" + + " [pc: 43, line: 19]\n" + + " [pc: 51, line: 21]\n" + + " [pc: 53, line: 22]\n" + + " Local variable table:\n" + + " [pc: 0, pc: 56] local: this index: 0 type: X\n" + + " [pc: 0, pc: 56] local: param index: 1 type: java.lang.Object\n" + + " [pc: 17, pc: 20] local: local index: 2 type: java.lang.Object\n" + + " [pc: 35, pc: 37] local: local index: 2 type: java.lang.Object\n" + + " [pc: 53, pc: 56] local: local index: 2 type: java.lang.Object\n" + + " [pc: 21, pc: 37] local: e index: 3 type: java.lang.RuntimeException\n" + + " Stack map table: number of frames 5\n" + + " [pc: 15, full, stack: {}, locals: {X, java.lang.Object, _, _, _, java.lang.Object}]\n" + + " [pc: 20, full, stack: {java.lang.RuntimeException}, locals: {X, java.lang.Object}]\n" + + " [pc: 33, full, stack: {}, locals: {X, java.lang.Object, _, java.lang.RuntimeException}]\n" + + " [pc: 37, full, stack: {java.lang.Throwable}, locals: {X, java.lang.Object}]\n" + + " [pc: 51, full, stack: {}, locals: {X, java.lang.Object, _, _, java.lang.Throwable}]\n" + + "}"; + + int index = actualOutput.indexOf(expectedOutput); + if (index == -1 || expectedOutput.length() == 0) { + System.out.println(Util.displayString(actualOutput, 2)); + } + if (index == -1) { + assertEquals("Wrong contents", expectedOutput, actualOutput); + } + } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrameCodeStream.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrameCodeStream.java index 08416a0911..6ec5a231d9 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrameCodeStream.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrameCodeStream.java @@ -142,31 +142,13 @@ public StackMapFrameCodeStream(ClassFile givenClassFile) { } public void addDefinitelyAssignedVariables(Scope scope, int initStateIndex) { // Required to fix 1PR0XVS: LFRE:WINNT - Compiler: variable table for method appears incorrect - loop: for (int i = 0; i < this.visibleLocalsCount; i++) { + for (int i = 0; i < this.visibleLocalsCount; i++) { LocalVariableBinding localBinding = this.visibleLocals[i]; if (localBinding != null) { // Check if the local is definitely assigned boolean isDefinitelyAssigned = isDefinitelyAssigned(scope, initStateIndex, localBinding); if (!isDefinitelyAssigned) { - if (this.stateIndexes != null) { - for (int j = 0, max = this.stateIndexesCounter; j < max; j++) { - if (isDefinitelyAssigned(scope, this.stateIndexes[j], localBinding)) { - if ((localBinding.initializationCount == 0) || (localBinding.initializationPCs[((localBinding.initializationCount - 1) << 1) + 1] != -1)) { - /* There are two cases: - * 1) there is no initialization interval opened ==> add an opened interval - * 2) there is already some initialization intervals but the last one is closed ==> add an opened interval - * An opened interval means that the value at localBinding.initializationPCs[localBinding.initializationCount - 1][1] - * is equals to -1. - * initializationPCs is a collection of pairs of int: - * first value is the startPC and second value is the endPC. -1 one for the last value means that the interval - * is not closed yet. - */ - localBinding.recordInitializationStartPC(this.position); - } - continue loop; - } - } - } + continue; } else { if ((localBinding.initializationCount == 0) || (localBinding.initializationPCs[((localBinding.initializationCount - 1) << 1) + 1] != -1)) { /* There are two cases: -- cgit v1.2.3