diff --git a/jasm-composition-jvm/src/main/java/me/darknet/assembler/compile/analysis/jvm/JvmAnalysisEngine.java b/jasm-composition-jvm/src/main/java/me/darknet/assembler/compile/analysis/jvm/JvmAnalysisEngine.java index cec0196..9f0d1cb 100644 --- a/jasm-composition-jvm/src/main/java/me/darknet/assembler/compile/analysis/jvm/JvmAnalysisEngine.java +++ b/jasm-composition-jvm/src/main/java/me/darknet/assembler/compile/analysis/jvm/JvmAnalysisEngine.java @@ -1,6 +1,8 @@ package me.darknet.assembler.compile.analysis.jvm; import dev.xdark.blw.code.CodeElement; +import dev.xdark.blw.type.ArrayType; +import dev.xdark.blw.type.ObjectType; import me.darknet.assembler.ast.primitive.ASTInstruction; import me.darknet.assembler.compile.analysis.AnalysisException; import me.darknet.assembler.compile.analysis.AnalysisResults; @@ -129,7 +131,10 @@ public void execute(ConditionalJumpInstruction instruction) { @Override public void execute(AllocateInstruction instruction) { - frame.pushType(instruction.type()); + ObjectType type = instruction.type(); + if (type instanceof ArrayType) + frame.pop(1); // pop array size off stack + frame.pushType(type); } @Override diff --git a/jasm-composition-jvm/src/main/java/me/darknet/assembler/compile/analysis/jvm/TypedJvmAnalysisEngine.java b/jasm-composition-jvm/src/main/java/me/darknet/assembler/compile/analysis/jvm/TypedJvmAnalysisEngine.java index 52ee1b7..bd5525f 100644 --- a/jasm-composition-jvm/src/main/java/me/darknet/assembler/compile/analysis/jvm/TypedJvmAnalysisEngine.java +++ b/jasm-composition-jvm/src/main/java/me/darknet/assembler/compile/analysis/jvm/TypedJvmAnalysisEngine.java @@ -63,8 +63,8 @@ public void execute(SimpleInstruction instruction) { ClassType type4 = frame.pop(); frame.pushTypes(type2, type1, type4, type3, type2, type1); } - case POP, IINC, IRETURN, LRETURN, FRETURN, DRETURN, ARETURN, MONITORENTER, MONITOREXIT -> frame.pop(); - case POP2 -> frame.pop2(); + case POP, IINC, IRETURN, FRETURN, ARETURN, MONITORENTER, MONITOREXIT -> frame.pop(); + case POP2, LRETURN, DRETURN -> frame.pop2(); case SWAP -> { ClassType type1 = frame.pop(); ClassType type2 = frame.pop(); diff --git a/jasm-composition-jvm/src/main/java/me/darknet/assembler/compile/analysis/jvm/ValuedJvmAnalysisEngine.java b/jasm-composition-jvm/src/main/java/me/darknet/assembler/compile/analysis/jvm/ValuedJvmAnalysisEngine.java index f70753b..ecd8c33 100644 --- a/jasm-composition-jvm/src/main/java/me/darknet/assembler/compile/analysis/jvm/ValuedJvmAnalysisEngine.java +++ b/jasm-composition-jvm/src/main/java/me/darknet/assembler/compile/analysis/jvm/ValuedJvmAnalysisEngine.java @@ -92,8 +92,8 @@ public void execute(SimpleInstruction instruction) { Value value4 = frame.pop(); frame.push(value2, value1, value4, value3, value2, value1); } - case POP, IRETURN, LRETURN, FRETURN, DRETURN, ARETURN, MONITORENTER, MONITOREXIT -> frame.pop(); - case POP2 -> frame.pop2(); + case POP, IRETURN, FRETURN, ARETURN, MONITORENTER, MONITOREXIT -> frame.pop(); + case POP2, LRETURN, DRETURN -> frame.pop2(); case SWAP -> { Value value1 = frame.pop(); Value value2 = frame.pop(); diff --git a/jasm-composition-jvm/src/test/java/me/darknet/assembler/SampleCompilerTest.java b/jasm-composition-jvm/src/test/java/me/darknet/assembler/SampleCompilerTest.java index 11b7328..8e9e03f 100644 --- a/jasm-composition-jvm/src/test/java/me/darknet/assembler/SampleCompilerTest.java +++ b/jasm-composition-jvm/src/test/java/me/darknet/assembler/SampleCompilerTest.java @@ -135,6 +135,19 @@ void fieldLookup() throws Throwable { @Nested class Regresssion { + @Test + void newArrayPopsSizeOffStack() throws Throwable { + TestArgument arg = TestArgument.fromName("Example-anewarray.jasm"); + String source = arg.source.get(); + TestJvmCompilerOptions options = new TestJvmCompilerOptions(); + options.engineProvider(ValuedJvmAnalysisEngine::new); + processJvm(source, options, classRepresentation -> { + AnalysisResults results = classRepresentation.analysisLookup().allResults().values().iterator().next(); + assertNull(results.getAnalysisFailure()); + assertFalse(results.terminalFrames().isEmpty()); + }); + } + @Test void athrowDoesNotAllowFlowThroughToNextFrameAndClearsStack() throws Throwable { TestArgument arg = TestArgument.fromName("Example-exit-exception.jasm"); diff --git a/jasm-composition-jvm/src/test/resources/samples/jasm/Example-anewarray.jasm b/jasm-composition-jvm/src/test/resources/samples/jasm/Example-anewarray.jasm index 9dd26de..d701f94 100644 --- a/jasm-composition-jvm/src/test/resources/samples/jasm/Example-anewarray.jasm +++ b/jasm-composition-jvm/src/test/resources/samples/jasm/Example-anewarray.jasm @@ -2,11 +2,37 @@ .class public super Example { .method public exampleMethod ()V { parameters: { this }, + exceptions: { { C, D, E, Ljava/lang/Exception; } }, code: { - A: - anewarray Ljava/lang/Object; - return - B: + A: + aload this + ifnull H + B: + iconst_0 + ifeq G + C: + nop + nop + D: + goto F + E: + astore ex + F: + goto B + G: + getstatic Example.log Ljava/util/logging/Logger; + ldc "foo" + iconst_1 + anewarray Ljava/lang/Object; + dup + iconst_0 + aload this + aastore + invokestatic Example.buildLogMessage (Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String; + invokevirtual java/util/logging/Logger.info (Ljava/lang/String;)V + H: + return + I: } } } \ No newline at end of file