From c3ff7141ab962d2cc1621594e12d5fef79eb3a9b Mon Sep 17 00:00:00 2001 From: upnotes Date: Wed, 3 Oct 2018 17:19:32 +0200 Subject: [PATCH] Preventing duplicate field access --- .../decompiler/SimplifyExprentsHelper.java | 44 +++++++++++- .../DominatorTreeExceptionFilter.java | 5 +- .../modules/decompiler/exps/FieldExprent.java | 2 +- .../classes/pkg/TestFieldSingleAccess.class | Bin 0 -> 588 bytes testData/results/TestFieldSingleAccess.dec | 40 +++++++++++ .../results/TestMethodReferenceSameName.dec | 12 ++-- testData/src/pkg/TestFieldSingleAccess.jasm | 67 ++++++++++++++++++ 7 files changed, 159 insertions(+), 11 deletions(-) create mode 100644 testData/classes/pkg/TestFieldSingleAccess.class create mode 100644 testData/results/TestFieldSingleAccess.dec create mode 100644 testData/src/pkg/TestFieldSingleAccess.jasm diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/SimplifyExprentsHelper.java b/src/org/jetbrains/java/decompiler/modules/decompiler/SimplifyExprentsHelper.java index 0bade66..f23fc78 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/SimplifyExprentsHelper.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/SimplifyExprentsHelper.java @@ -178,7 +178,7 @@ public class SimplifyExprentsHelper { } // expr++ and expr-- - if (isIPPorIMM(current, next)) { + if (isIPPorIMM(current, next) || isIPPorIMM2(current, next)) { list.remove(index + 1); res = true; continue; @@ -458,6 +458,48 @@ public class SimplifyExprentsHelper { return false; } + private static boolean isIPPorIMM2(Exprent first, Exprent second) { + + if (first.type != Exprent.EXPRENT_ASSIGNMENT || second.type != Exprent.EXPRENT_ASSIGNMENT) { + return false; + } + + AssignmentExprent af = (AssignmentExprent)first; + AssignmentExprent as = (AssignmentExprent)second; + + if(as.getRight().type != Exprent.EXPRENT_FUNCTION) { + return false; + } + + FunctionExprent func = (FunctionExprent)as.getRight(); + + if(func.getFuncType() != FunctionExprent.FUNCTION_ADD && func.getFuncType() != FunctionExprent.FUNCTION_SUB) { + return false; + } + + Exprent econd = func.getLstOperands().get(0); + Exprent econst = func.getLstOperands().get(1); + + if(econst.type != Exprent.EXPRENT_CONST && econd.type == Exprent.EXPRENT_CONST && func.getFuncType() == FunctionExprent.FUNCTION_ADD) { + econd = econst; + econst = func.getLstOperands().get(0); + } + + if(econst.type == Exprent.EXPRENT_CONST && ((ConstExprent)econst).hasValueOne()) { + if(af.getLeft().equals(econd) && af.getRight().equals(as.getLeft()) && (af.getLeft().getExprentUse() & Exprent.MULTIPLE_USES) != 0) { + int type = func.getFuncType() == FunctionExprent.FUNCTION_ADD ? FunctionExprent.FUNCTION_IPP : FunctionExprent.FUNCTION_IMM; + + FunctionExprent ret = new FunctionExprent(type, af.getRight(), func.bytecode); + ret.setImplicitType(VarType.VARTYPE_INT); + + af.setRight(ret); + return true; + } + } + + return false; + } + private static boolean isMonitorExit(Exprent first) { if (first.type == Exprent.EXPRENT_MONITOR) { MonitorExprent expr = (MonitorExprent)first; diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/decompose/DominatorTreeExceptionFilter.java b/src/org/jetbrains/java/decompiler/modules/decompiler/decompose/DominatorTreeExceptionFilter.java index 89babeb..d8b587f 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/decompose/DominatorTreeExceptionFilter.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/decompose/DominatorTreeExceptionFilter.java @@ -134,8 +134,9 @@ public class DominatorTreeExceptionFilter { exit = childid; } else { - // exit = map.containsKey(handler)?-1:mapChild.get(handler); FIXME: Eclipse bug? - exit = map.containsKey(handler) ? -1 : mapChild.get(handler); + // after replacing 'new Integer(-1)' with '-1' Eclipse throws a NullPointerException on the following line + // could be a bug in Eclipse or some obscure specification glitch, FIXME: needs further investigation + exit = map.containsKey(handler) ? new Integer(-1) : mapChild.get(handler); } if (exit != null) { diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java index 264347e..642a86b 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java @@ -54,7 +54,7 @@ public class FieldExprent extends Exprent { @Override public int getExprentUse() { - return instance == null ? Exprent.MULTIPLE_USES : instance.getExprentUse() & Exprent.MULTIPLE_USES; + return 0; // multiple references to a field considered dangerous in a multithreaded environment, thus no Exprent.MULTIPLE_USES set here } @Override diff --git a/testData/classes/pkg/TestFieldSingleAccess.class b/testData/classes/pkg/TestFieldSingleAccess.class new file mode 100644 index 0000000000000000000000000000000000000000..edc30abd1f133b25e84ae96652ce8b99d37245b6 GIT binary patch literal 588 zcmZutT}vB56g{)~m}I-ws7b4-U$rg7SPX%_MFbH9L9wzy@JZHn8aHlt!|rJ5FY2=* z3O-n<;6s0s585*Zzn~1;}|nxx`_99S418YHYym9C<|n2 zvs(h$+OkO_UGKZdo*P7+P%ZhsO4IqSmwp$>F9cDb z7X@o=QXGFt@HlFFNMp|`L(xQ!i^`*O(gEuHi6dk*60U+{1MZyDaW8paQN4c&KuT>Tum zV-`$l=CS<=76Cx1ev0h&HS7~)cFrISlK)}kxIt1TA1RxpWZ0 5 -6 <-> 8 -9 <-> 12 +6 <-> 7 +9 <-> 11 diff --git a/testData/src/pkg/TestFieldSingleAccess.jasm b/testData/src/pkg/TestFieldSingleAccess.jasm new file mode 100644 index 0000000..57b203c --- /dev/null +++ b/testData/src/pkg/TestFieldSingleAccess.jasm @@ -0,0 +1,67 @@ +/** + * This code can be assembled with asmtools + * using asmtools jasm -g *.jasm command line. + */ +package pkg; + +super public final class TestFieldSingleAccess + version 52:0 +{ + +public Field field:"Ljava/lang/Integer;"; + +public Method "":"()V" + stack 1 locals 1 +{ + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; +} + +public final Method test:"()V" + stack 2 locals 1 +{ + aload_0; + getfield Field field:"Ljava/lang/Integer;"; + dup; + ifnull L17; + getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; + swap; + invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/Object;)V"; + L17: stack_frame_type same; + return; +} + +public final Method test1:"()V" + stack 2 locals 3 +{ + aload_0; + getfield Field field:"Ljava/lang/Integer;"; + dup; + astore_1; + monitorenter; + try t0; + getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; + bipush 49; + invokevirtual Method java/io/PrintStream.println:"(C)V"; + aload_1; + monitorexit; + endtry t0; + goto L25; + catch t0 #0; + catch t1 #0; + try t1; + stack_frame_type full; + locals_map class TestFieldSingleAccess, class java/lang/Object; + stack_map class java/lang/Throwable; + astore_2; + aload_1; + monitorexit; + endtry t1; + aload_2; + athrow; + L25: stack_frame_type chop1; + return; +} + +} // end Class TestFieldSingleAccess