From e7854376b8a6225403943290d5d57d26bffa119b Mon Sep 17 00:00:00 2001 From: Maxim Degtyarev Date: Wed, 18 Oct 2017 09:43:38 +0300 Subject: [PATCH] [PATCH] Fix POP2 opcode handling bug with two category 1 values at the stack top. --- .../modules/decompiler/ExprProcessor.java | 27 ++++++--------- .../java/decompiler/SingleClassesTest.java | 20 +++-------- .../classes/pkg/TestPop2OneDoublePop2.class | Bin 0 -> 459 bytes .../classes/pkg/TestPop2OneLongPop2.class | Bin 0 -> 455 bytes testData/classes/pkg/TestPop2TwoIntPop2.class | Bin 0 -> 459 bytes .../classes/pkg/TestPop2TwoIntTwoPop.class | Bin 0 -> 468 bytes testData/results/TestPop2OneDoublePop2.dec | 27 +++++++++++++++ testData/results/TestPop2OneLongPop2.dec | 27 +++++++++++++++ testData/results/TestPop2TwoIntPop2.dec | 30 ++++++++++++++++ testData/results/TestPop2TwoIntTwoPop.dec | 31 +++++++++++++++++ testData/src/pkg/TestPop2OneDoublePop2.jasm | 30 ++++++++++++++++ testData/src/pkg/TestPop2OneLongPop2.jasm | 30 ++++++++++++++++ testData/src/pkg/TestPop2TwoIntPop2.jasm | 31 +++++++++++++++++ testData/src/pkg/TestPop2TwoIntTwoPop.jasm | 32 ++++++++++++++++++ 14 files changed, 254 insertions(+), 31 deletions(-) create mode 100644 testData/classes/pkg/TestPop2OneDoublePop2.class create mode 100644 testData/classes/pkg/TestPop2OneLongPop2.class create mode 100644 testData/classes/pkg/TestPop2TwoIntPop2.class create mode 100644 testData/classes/pkg/TestPop2TwoIntTwoPop.class create mode 100644 testData/results/TestPop2OneDoublePop2.dec create mode 100644 testData/results/TestPop2OneLongPop2.dec create mode 100644 testData/results/TestPop2TwoIntPop2.dec create mode 100644 testData/results/TestPop2TwoIntTwoPop.dec create mode 100644 testData/src/pkg/TestPop2OneDoublePop2.jasm create mode 100644 testData/src/pkg/TestPop2OneLongPop2.jasm create mode 100644 testData/src/pkg/TestPop2TwoIntPop2.jasm create mode 100644 testData/src/pkg/TestPop2TwoIntTwoPop.jasm diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java b/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java index c21f11d..48e7d3f 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.java.decompiler.modules.decompiler; import org.jetbrains.java.decompiler.code.CodeConstants; @@ -618,8 +604,17 @@ public class ExprProcessor implements CodeConstants { stack.pop(); break; case opc_pop: - case opc_pop2: stack.pop(); + break; + case opc_pop2: + if (stack.getByOffset(-1).getExprType().stackSize == 1) { + // Since value at the top of the stack is a value of category 1 (JVMS9 2.11.1) + // we should remove one more item from the stack. + // See JVMS9 pop2 chapter. + stack.pop(); + } + stack.pop(); + break; } } } diff --git a/test/org/jetbrains/java/decompiler/SingleClassesTest.java b/test/org/jetbrains/java/decompiler/SingleClassesTest.java index fd48f0d..2e6c819 100644 --- a/test/org/jetbrains/java/decompiler/SingleClassesTest.java +++ b/test/org/jetbrains/java/decompiler/SingleClassesTest.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.java.decompiler; import org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler; @@ -111,6 +97,10 @@ public class SingleClassesTest { @Test public void testLambdaParams() { doTest("pkg/TestLambdaParams"); } @Test public void testInterfaceMethods() { doTest("pkg/TestInterfaceMethods"); } @Test public void testConstType() { doTest("pkg/TestConstType"); } + @Test public void testPop2OneDoublePop2() { doTest("pkg/TestPop2OneDoublePop2"); } + @Test public void testPop2OneLongPop2() { doTest("pkg/TestPop2OneLongPop2"); } + @Test public void testPop2TwoIntPop2() { doTest("pkg/TestPop2TwoIntPop2"); } + @Test public void testPop2TwoIntTwoPop() { doTest("pkg/TestPop2TwoIntTwoPop"); } // TODO: fix all below //@Test public void testPackageInfo() { doTest("pkg/package-info"); } diff --git a/testData/classes/pkg/TestPop2OneDoublePop2.class b/testData/classes/pkg/TestPop2OneDoublePop2.class new file mode 100644 index 0000000000000000000000000000000000000000..1c41f76d4015c89f2a7ae036961398cd0a22e871 GIT binary patch literal 459 zcmZuu%SyvQ6g`uqjfrWkeYZZK3!%C&Aa0~0LPaPPTWAr%)wB*FHILFJf}h|I_#e7Z zaN!5Ibm5n{6U001q7aGY@x_t_QH5F6z8rd z81%7h^8y;XE~&M8OS-~bc$ua_O@Ch)JK*{5m$5UfR2#MuKFM$8O+8 zC#WGso03NXlT(nbP_{#!kx%TsLVcoumP0lTb!JHj8Zvl5mZCZ2h;Ae#^$aD;@SPfD*5Xxly?Rwe_5A1a3&1J%%+`zXox(OU4mMFp{F2Ryb&!S2Q0?=n z>c-=fj^yoF20A<*`O}EOjAzP*!%!JN1l~V&HqtIis4(P4{-f`Oz6`w1V8n;Y#RjT2 zwiwEdyY`Chsfmz5^YDhDu*izo>rzS)!F?KPMZS_1`cU$p=L literal 0 HcmV?d00001 diff --git a/testData/classes/pkg/TestPop2TwoIntPop2.class b/testData/classes/pkg/TestPop2TwoIntPop2.class new file mode 100644 index 0000000000000000000000000000000000000000..f227a65ae207f9e2744053b06eeed016dd8f4270 GIT binary patch literal 459 zcmZWm-AV#M6#iyc-P~5QHUG+lE&}bMh3L-kCI|#6L6M-V(FPgYofRF69-$ZLJ?f&s z3m?GC9!NTC7b4BYcmC#l-X(|XFFvJ2b zm4jns8SG9tn+(K_^aX=8j;{HNq^q@_g&a|jpN3vnOm#aPUvyu>rdoRph5yO(5uZl% z)n=rf`x|LnyiVoo@R79kT2hJISg*9X?U5Xmrtei5gN7l0$=4HF@d33Z}?dg-Q+{B|1l__*Wu0&bza@y_<^L~&wETnQ=EHI9&__2^@O z>G=suk^VgYwKS^nP@9SuuBvM^1rgOUH$+7 literal 0 HcmV?d00001 diff --git a/testData/results/TestPop2OneDoublePop2.dec b/testData/results/TestPop2OneDoublePop2.dec new file mode 100644 index 0000000..95ceaee --- /dev/null +++ b/testData/results/TestPop2OneDoublePop2.dec @@ -0,0 +1,27 @@ +package pkg; + +public class TestPop2OneDoublePop2 { + public static void main(String... var0) { + double var10002 = 3.14159265358D;// 24 + System.out.println(1234567890);// 22 23 26 + }// 27 +} + +class 'pkg/TestPop2OneDoublePop2' { + method 'main ([Ljava/lang/String;)V' { + 0 5 + 3 5 + 5 4 + 9 5 + c 6 + } +} + +Lines mapping: +22 <-> 6 +23 <-> 6 +24 <-> 5 +26 <-> 6 +27 <-> 7 +Not mapped: +25 diff --git a/testData/results/TestPop2OneLongPop2.dec b/testData/results/TestPop2OneLongPop2.dec new file mode 100644 index 0000000..2d78133 --- /dev/null +++ b/testData/results/TestPop2OneLongPop2.dec @@ -0,0 +1,27 @@ +package pkg; + +public class TestPop2OneLongPop2 { + public static void main(String... var0) { + long var10002 = -889275714L;// 24 + System.out.println(1234567890);// 22 23 26 + }// 27 +} + +class 'pkg/TestPop2OneLongPop2' { + method 'main ([Ljava/lang/String;)V' { + 0 5 + 3 5 + 5 4 + 9 5 + c 6 + } +} + +Lines mapping: +22 <-> 6 +23 <-> 6 +24 <-> 5 +26 <-> 6 +27 <-> 7 +Not mapped: +25 diff --git a/testData/results/TestPop2TwoIntPop2.dec b/testData/results/TestPop2TwoIntPop2.dec new file mode 100644 index 0000000..9d1583c --- /dev/null +++ b/testData/results/TestPop2TwoIntPop2.dec @@ -0,0 +1,30 @@ +package pkg; + +public class TestPop2TwoIntPop2 { + public static void main(String... var0) { + char var10002 = '쫾';// 24 + char var10003 = '몾';// 25 + System.out.println(1234567890);// 22 23 27 + }// 28 +} + +class 'pkg/TestPop2TwoIntPop2' { + method 'main ([Ljava/lang/String;)V' { + 0 6 + 3 6 + 5 4 + 7 5 + a 6 + d 7 + } +} + +Lines mapping: +22 <-> 7 +23 <-> 7 +24 <-> 5 +25 <-> 6 +27 <-> 7 +28 <-> 8 +Not mapped: +26 diff --git a/testData/results/TestPop2TwoIntTwoPop.dec b/testData/results/TestPop2TwoIntTwoPop.dec new file mode 100644 index 0000000..aaa360b --- /dev/null +++ b/testData/results/TestPop2TwoIntTwoPop.dec @@ -0,0 +1,31 @@ +package pkg; + +public class TestPop2TwoIntTwoPop { + public static void main(String... var0) { + char var10002 = '쫾';// 24 + char var10003 = '몾';// 25 + System.out.println(1234567890);// 22 23 28 + }// 29 +} + +class 'pkg/TestPop2TwoIntTwoPop' { + method 'main ([Ljava/lang/String;)V' { + 0 6 + 3 6 + 5 4 + 7 5 + b 6 + e 7 + } +} + +Lines mapping: +22 <-> 7 +23 <-> 7 +24 <-> 5 +25 <-> 6 +28 <-> 7 +29 <-> 8 +Not mapped: +26 +27 diff --git a/testData/src/pkg/TestPop2OneDoublePop2.jasm b/testData/src/pkg/TestPop2OneDoublePop2.jasm new file mode 100644 index 0000000..6f7d5f6 --- /dev/null +++ b/testData/src/pkg/TestPop2OneDoublePop2.jasm @@ -0,0 +1,30 @@ +/** + * This code can be assembled with asmtools + * using asmtools jasm -g *.jasm command line. + */ +package pkg; + +super public class TestPop2OneDoublePop2 + version 52:0 +{ + +public Method "":"()V" + stack 1 locals 1 +{ + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; +} + +public static varargs Method main:"([Ljava/lang/String;)V" + stack 4 locals 1 +{ + getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; + ldc int 1234567890; + ldc2_w double 3.14159265358D; + pop2; + invokevirtual Method java/io/PrintStream.println:"(I)V"; + return; +} + +} // end Class TestPop2OneDoublePop2 diff --git a/testData/src/pkg/TestPop2OneLongPop2.jasm b/testData/src/pkg/TestPop2OneLongPop2.jasm new file mode 100644 index 0000000..62d3179 --- /dev/null +++ b/testData/src/pkg/TestPop2OneLongPop2.jasm @@ -0,0 +1,30 @@ +/** + * This code can be assembled with asmtools + * using asmtools jasm -g *.jasm command line. + */ +package pkg; + +super public class TestPop2OneLongPop2 + version 52:0 +{ + +public Method "":"()V" + stack 1 locals 1 +{ + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; +} + +public static varargs Method main:"([Ljava/lang/String;)V" + stack 4 locals 1 +{ + getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; + ldc int 1234567890; + ldc2_w long 0xCAFEBABE; + pop2; + invokevirtual Method java/io/PrintStream.println:"(I)V"; + return; +} + +} // end Class TestPop2OneLongPop2 diff --git a/testData/src/pkg/TestPop2TwoIntPop2.jasm b/testData/src/pkg/TestPop2TwoIntPop2.jasm new file mode 100644 index 0000000..4f2ce8e --- /dev/null +++ b/testData/src/pkg/TestPop2TwoIntPop2.jasm @@ -0,0 +1,31 @@ +/** + * This code can be assembled with asmtools + * using asmtools jasm -g *.jasm command line. + */ +package pkg; + +super public class TestPop2TwoIntPop2 + version 52:0 +{ + +public Method "":"()V" + stack 1 locals 1 +{ + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; +} + +public static varargs Method main:"([Ljava/lang/String;)V" + stack 4 locals 1 +{ + getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; + ldc int 1234567890; + ldc int 0xCAFE; + ldc int 0xBABE; + pop2; + invokevirtual Method java/io/PrintStream.println:"(I)V"; + return; +} + +} // end Class TestPop2TwoIntPop2 diff --git a/testData/src/pkg/TestPop2TwoIntTwoPop.jasm b/testData/src/pkg/TestPop2TwoIntTwoPop.jasm new file mode 100644 index 0000000..c9292da --- /dev/null +++ b/testData/src/pkg/TestPop2TwoIntTwoPop.jasm @@ -0,0 +1,32 @@ +/** + * This code can be assembled with asmtools + * using asmtools jasm -g *.jasm command line. + */ +package pkg; + +super public class TestPop2TwoIntTwoPop + version 52:0 +{ + +public Method "":"()V" + stack 1 locals 1 +{ + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; +} + +public static varargs Method main:"([Ljava/lang/String;)V" + stack 4 locals 1 +{ + getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; + ldc int 1234567890; + ldc int 0xCAFE; + ldc int 0xBABE; + pop; + pop; + invokevirtual Method java/io/PrintStream.println:"(I)V"; + return; +} + +} // end Class TestPop2TwoIntTwoPop