From 1fd2fe265b48fc03426004cbc8c5cafd5f63c774 Mon Sep 17 00:00:00 2001 From: Markus Schmidt Date: Mon, 17 Jul 2023 12:30:16 +0200 Subject: [PATCH 01/36] fix off by one: iterating over a all type items; adapt it according to old soots implementation --- .../sootup/java/bytecode/frontend/AsmMethodSource.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java b/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java index 067aa461843..a9f06720a6e 100644 --- a/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java +++ b/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java @@ -1345,7 +1345,7 @@ private void convertInvokeDynamicInsn(@Nonnull InvokeDynamicInsnNode insn) { // Generate parameters & returnType & parameterTypes List types = AsmUtil.toJimpleSignatureDesc(insn.desc); - int nrArgs = types.size() - 1; + int nrArgs = types.size() - 1; // don't handle the return type here List parameterTypes = new ArrayList<>(nrArgs); List methodArgs = new ArrayList<>(nrArgs); @@ -1383,12 +1383,12 @@ private void convertInvokeDynamicInsn(@Nonnull InvokeDynamicInsnNode insn) { AbstractInvokeExpr expr = (AbstractInvokeExpr) opr.value; List types = expr.getMethodSignature().getParameterTypes(); Operand[] oprs; - int nrArgs = types.size() - 1; + int nrArgs = types.size(); final boolean isStaticInvokeExpr = expr instanceof JStaticInvokeExpr; if (isStaticInvokeExpr) { - oprs = (nrArgs <= 0) ? null : new Operand[nrArgs]; + oprs = (nrArgs == 0) ? null : new Operand[nrArgs]; } else { - oprs = (nrArgs < 0) ? null : new Operand[nrArgs + 1]; + oprs = new Operand[nrArgs + 1]; } if (oprs != null) { while (nrArgs-- > 0) { From f5420790d9770eca114bb7d5114d2765364bd445 Mon Sep 17 00:00:00 2001 From: Markus Schmidt Date: Mon, 17 Jul 2023 12:30:31 +0200 Subject: [PATCH 02/36] cleanup --- .../bytecode/frontend/AsmMethodSource.java | 33 +++---------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java b/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java index a9f06720a6e..3fa2fdfdf04 100644 --- a/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java +++ b/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java @@ -1345,7 +1345,7 @@ private void convertInvokeDynamicInsn(@Nonnull InvokeDynamicInsnNode insn) { // Generate parameters & returnType & parameterTypes List types = AsmUtil.toJimpleSignatureDesc(insn.desc); - int nrArgs = types.size() - 1; // don't handle the return type here + int nrArgs = types.size() - 1; // don't handle the return type here List parameterTypes = new ArrayList<>(nrArgs); List methodArgs = new ArrayList<>(nrArgs); @@ -1353,8 +1353,9 @@ private void convertInvokeDynamicInsn(@Nonnull InvokeDynamicInsnNode insn) { // Beware: Call stack is FIFO, Jimple is linear for (int i = nrArgs - 1; i >= 0; i--) { - parameterTypes.add(types.get(i)); - args[i] = operandStack.popImmediate(types.get(i)); + final Type type = types.get(i); + parameterTypes.add(type); + args[i] = operandStack.popImmediate(type); methodArgs.add((Immediate) args[i].stackOrValue()); } if (methodArgs.size() > 1) { @@ -1418,32 +1419,6 @@ private void convertInvokeDynamicInsn(@Nonnull InvokeDynamicInsnNode insn) { addReadOperandAssignments(); } - // private @Nonnull MethodRef toSootMethodRef(@Nonnull Handle methodHandle) { - // String bsmClsName = AsmUtil.toQualifiedName(methodHandle.getOwner()); - // JavaClassType bsmCls = view.getIdentifierFactory().getClassSignature(bsmClsName); - // List bsmSigTypes = AsmUtil.toJimpleSignatureDesc(methodHandle.getDesc(), view); - // Type returnType = bsmSigTypes.remove(bsmSigTypes.size() - 1); - // MethodSignature methodSignature = - // view.getIdentifierFactory().getMethodSignature(methodHandle.getName(), bsmCls, - // returnType, bsmSigTypes); - // boolean isStatic = methodHandle.getTag() == MethodHandle.Kind.REF_INVOKE_STATIC.getValue(); - // return Jimple.createSymbolicMethodRef(methodSignature, isStatic); - // } - // - // private JFieldRef toSootFieldRef(Handle methodHandle) { - // String bsmClsName = AsmUtil.toQualifiedName(methodHandle.getOwner()); - // JavaClassType bsmCls = view.getIdentifierFactory().getClassSignature(bsmClsName); - // - // Type t = AsmUtil.toJimpleSignatureDesc(methodHandle.getDesc(), view).get(0); - // int kind = methodHandle.getTag(); - // boolean isStatic = kind == MethodHandle.Kind.REF_GET_FIELD_STATIC.getValue() - // || kind == MethodHandle.Kind.REF_PUT_FIELD_STATIC.getValue(); - // - // FieldSignature fieldSignature = - // view.getIdentifierFactory().getFieldSignature(methodHandle.getName(), bsmCls, t); - // return Jimple.createSymbolicFieldRef(fieldSignature, isStatic); - // } - private void convertMultiANewArrayInsn(@Nonnull MultiANewArrayInsnNode insn) { StackFrame frame = operandStack.getOrCreateStackframe(insn); Operand[] out = frame.getOut(); From bc479395925ec47fc41c869ed3ce29c699aca9c2 Mon Sep 17 00:00:00 2001 From: Markus Schmidt Date: Wed, 2 Aug 2023 13:46:41 +0200 Subject: [PATCH 03/36] create ctor; use memory efficient variant to store just line numbers --- .../jimple/basic/FullStmtPositionInfo.java | 7 +++--- .../jimple/basic/SimpleStmtPositionInfo.java | 16 ++----------- .../core/jimple/basic/StmtPositionInfo.java | 23 ++----------------- .../java/sootup/core/model/LinePosition.java | 6 ++++- 4 files changed, 12 insertions(+), 40 deletions(-) diff --git a/sootup.core/src/main/java/sootup/core/jimple/basic/FullStmtPositionInfo.java b/sootup.core/src/main/java/sootup/core/jimple/basic/FullStmtPositionInfo.java index 058e4fdc1bc..dfa3a785388 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/basic/FullStmtPositionInfo.java +++ b/sootup.core/src/main/java/sootup/core/jimple/basic/FullStmtPositionInfo.java @@ -23,7 +23,6 @@ */ import javax.annotation.Nonnull; -import sootup.core.model.FullPosition; import sootup.core.model.Position; import sootup.core.util.Copyable; @@ -34,7 +33,7 @@ * @author Linghui Luo, Markus Schmidt */ public class FullStmtPositionInfo extends SimpleStmtPositionInfo implements Copyable { - protected final FullPosition[] operandPositions; + @Nonnull protected final Position[] operandPositions; /** * Create an instance from given statement position and operand positions. @@ -43,7 +42,7 @@ public class FullStmtPositionInfo extends SimpleStmtPositionInfo implements Copy * @param operandPositions the operand positions */ public FullStmtPositionInfo( - @Nonnull Position stmtPosition, @Nonnull FullPosition[] operandPositions) { + @Nonnull Position stmtPosition, @Nonnull Position[] operandPositions) { super(stmtPosition); this.operandPositions = operandPositions; } @@ -94,7 +93,7 @@ public StmtPositionInfo withStmtPosition(@Nonnull Position stmtPosition) { } @Nonnull - public StmtPositionInfo withOperandPositions(@Nonnull FullPosition[] operandPositions) { + public StmtPositionInfo withOperandPositions(@Nonnull Position[] operandPositions) { return new FullStmtPositionInfo(stmtPosition, operandPositions); } } diff --git a/sootup.core/src/main/java/sootup/core/jimple/basic/SimpleStmtPositionInfo.java b/sootup.core/src/main/java/sootup/core/jimple/basic/SimpleStmtPositionInfo.java index 10275f0fa13..7f30a58d2fa 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/basic/SimpleStmtPositionInfo.java +++ b/sootup.core/src/main/java/sootup/core/jimple/basic/SimpleStmtPositionInfo.java @@ -24,7 +24,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; -import sootup.core.model.FullPosition; +import sootup.core.model.LinePosition; import sootup.core.model.Position; /** @@ -47,7 +47,7 @@ public SimpleStmtPositionInfo(@Nonnull Position stmtPosition) { * @param lineNumber the line number of the statement. */ public SimpleStmtPositionInfo(int lineNumber) { - stmtPosition = new FullPosition(lineNumber, -1, lineNumber, -1); + stmtPosition = new LinePosition(lineNumber); } @Nonnull @@ -67,16 +67,4 @@ public String toString() { s.append("stmt at:").append(getStmtPosition()).append("\n"); return s.toString(); } - - @Nonnull - @Override - public StmtPositionInfo withStmtPosition(@Nonnull Position stmtPosition) { - return null; - } - - @Nonnull - @Override - public StmtPositionInfo withOperandPositions(@Nonnull FullPosition[] operandPositions) { - return null; - } } diff --git a/sootup.core/src/main/java/sootup/core/jimple/basic/StmtPositionInfo.java b/sootup.core/src/main/java/sootup/core/jimple/basic/StmtPositionInfo.java index b65dddd380b..692732326e7 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/basic/StmtPositionInfo.java +++ b/sootup.core/src/main/java/sootup/core/jimple/basic/StmtPositionInfo.java @@ -24,7 +24,6 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; -import sootup.core.model.FullPosition; import sootup.core.model.Position; /** @@ -34,7 +33,7 @@ */ public abstract class StmtPositionInfo { - protected static final StmtPositionInfo noPosition = + protected static final StmtPositionInfo NOPOSITION = new StmtPositionInfo() { @Nonnull @Override @@ -51,18 +50,6 @@ public Position getOperandPosition(int index) { public String toString() { return "No StmtPositionnfo"; } - - @Nonnull - @Override - public StmtPositionInfo withStmtPosition(@Nonnull Position stmtPosition) { - return this; - } - - @Nonnull - @Override - public StmtPositionInfo withOperandPositions(@Nonnull FullPosition[] operandPositions) { - return this; - } }; /** @@ -72,7 +59,7 @@ public StmtPositionInfo withOperandPositions(@Nonnull FullPosition[] operandPosi */ @Nonnull public static StmtPositionInfo createNoStmtPositionInfo() { - return noPosition; + return NOPOSITION; } /** @@ -94,10 +81,4 @@ public static StmtPositionInfo createNoStmtPositionInfo() { @Override public abstract String toString(); - - @Nonnull - public abstract StmtPositionInfo withStmtPosition(@Nonnull Position stmtPosition); - - @Nonnull - public abstract StmtPositionInfo withOperandPositions(@Nonnull FullPosition[] operandPositions); } diff --git a/sootup.core/src/main/java/sootup/core/model/LinePosition.java b/sootup.core/src/main/java/sootup/core/model/LinePosition.java index 8dc130eadb2..624ffa88fb8 100644 --- a/sootup.core/src/main/java/sootup/core/model/LinePosition.java +++ b/sootup.core/src/main/java/sootup/core/model/LinePosition.java @@ -1,7 +1,11 @@ package sootup.core.model; public class LinePosition extends Position { - int lineNo; + private final int lineNo; + + public LinePosition(int lineNo) { + this.lineNo = lineNo; + } @Override public int getFirstLine() { From 70873efb680644b4a60a8dc4cb6c14f271c18881 Mon Sep 17 00:00:00 2001 From: Markus Schmidt Date: Thu, 3 Aug 2023 17:53:50 +0200 Subject: [PATCH 04/36] fixed nonnull. dry toString --- .../core/jimple/basic/FullStmtPositionInfo.java | 13 ++++--------- .../core/jimple/basic/SimpleStmtPositionInfo.java | 6 ------ .../sootup/core/jimple/basic/StmtPositionInfo.java | 6 +++++- .../frontend/WalaIRToJimpleConverter.java | 2 +- 4 files changed, 10 insertions(+), 17 deletions(-) diff --git a/sootup.core/src/main/java/sootup/core/jimple/basic/FullStmtPositionInfo.java b/sootup.core/src/main/java/sootup/core/jimple/basic/FullStmtPositionInfo.java index dfa3a785388..98dab8e2641 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/basic/FullStmtPositionInfo.java +++ b/sootup.core/src/main/java/sootup/core/jimple/basic/FullStmtPositionInfo.java @@ -64,7 +64,7 @@ public Position getStmtPosition() { * @return the position of the given operand */ public Position getOperandPosition(int index) { - if (this.operandPositions != null && index >= 0 && index < this.operandPositions.length) { + if (index >= 0 && index < this.operandPositions.length) { return this.operandPositions[index]; } else { return NoPositionInformation.getInstance(); @@ -74,15 +74,10 @@ public Position getOperandPosition(int index) { @Override public String toString() { StringBuilder s = new StringBuilder(); - s.append("stmt at: ").append(getStmtPosition()).append("\n"); + s.append(super.toString()); s.append("operands at: "); - if (operandPositions != null) { - s.append("\n"); - for (int i = 0; i < operandPositions.length; i++) { - s.append(i).append(": ").append(operandPositions[i]).append(" "); - } - } else { - s.append("No position info"); + for (int i = 0; i < operandPositions.length; i++) { + s.append(i).append(": ").append(operandPositions[i]).append(" "); } return s.toString(); } diff --git a/sootup.core/src/main/java/sootup/core/jimple/basic/SimpleStmtPositionInfo.java b/sootup.core/src/main/java/sootup/core/jimple/basic/SimpleStmtPositionInfo.java index 7f30a58d2fa..546cbe7a110 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/basic/SimpleStmtPositionInfo.java +++ b/sootup.core/src/main/java/sootup/core/jimple/basic/SimpleStmtPositionInfo.java @@ -61,10 +61,4 @@ public Position getStmtPosition() { public Position getOperandPosition(int index) { return null; } - - public String toString() { - StringBuilder s = new StringBuilder(); - s.append("stmt at:").append(getStmtPosition()).append("\n"); - return s.toString(); - } } diff --git a/sootup.core/src/main/java/sootup/core/jimple/basic/StmtPositionInfo.java b/sootup.core/src/main/java/sootup/core/jimple/basic/StmtPositionInfo.java index 692732326e7..769eb1bdf1b 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/basic/StmtPositionInfo.java +++ b/sootup.core/src/main/java/sootup/core/jimple/basic/StmtPositionInfo.java @@ -80,5 +80,9 @@ public static StmtPositionInfo createNoStmtPositionInfo() { public abstract Position getOperandPosition(int index); @Override - public abstract String toString(); + public String toString() { + StringBuilder s = new StringBuilder(); + s.append("stmt at:").append(getStmtPosition()); + return s.toString(); + } } diff --git a/sootup.java.sourcecode/src/main/java/sootup/java/sourcecode/frontend/WalaIRToJimpleConverter.java b/sootup.java.sourcecode/src/main/java/sootup/java/sourcecode/frontend/WalaIRToJimpleConverter.java index 4094732a53d..a204eec586d 100644 --- a/sootup.java.sourcecode/src/main/java/sootup/java/sourcecode/frontend/WalaIRToJimpleConverter.java +++ b/sootup.java.sourcecode/src/main/java/sootup/java/sourcecode/frontend/WalaIRToJimpleConverter.java @@ -645,7 +645,7 @@ public static StmtPositionInfo convertPositionInfo( Position instructionPosition, Position[] operandPosition) { if (operandPosition == null) { - return new FullStmtPositionInfo(convertPosition(instructionPosition), null); + return new SimpleStmtPositionInfo(convertPosition(instructionPosition)); } FullPosition[] operandPos = Arrays.stream(operandPosition) From 453bb7bd0d774056ce873cb49b6c5b31a7e24b40 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 11 Aug 2023 17:53:16 +0200 Subject: [PATCH 05/36] used FieldSignature instead of FieldRef in MethodHandle --- .../core/jimple/common/constant/MethodHandle.java | 14 ++++++++------ .../java/bytecode/frontend/AsmMethodSource.java | 9 ++++++++- .../java/sootup/java/core/language/JavaJimple.java | 4 ++-- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/constant/MethodHandle.java b/sootup.core/src/main/java/sootup/core/jimple/common/constant/MethodHandle.java index d7e0bf53303..58cfd51cd75 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/constant/MethodHandle.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/constant/MethodHandle.java @@ -23,8 +23,8 @@ */ import javax.annotation.Nonnull; -import sootup.core.jimple.common.ref.JFieldRef; import sootup.core.jimple.visitor.ConstantVisitor; +import sootup.core.signatures.FieldSignature; import sootup.core.signatures.MethodSignature; import sootup.core.types.Type; @@ -80,19 +80,19 @@ public static Kind getKind(String kind) { } private final MethodSignature methodSignature; - private final JFieldRef fieldRef; + private final FieldSignature fieldSignature; public int tag; public MethodHandle(MethodSignature methodSignature, int tag, Type type) { this.methodSignature = methodSignature; this.tag = tag; - this.fieldRef = null; + this.fieldSignature = null; this.type = type; } - public MethodHandle(JFieldRef ref, int tag, Type type) { - this.fieldRef = ref; + public MethodHandle(FieldSignature ref, int tag, Type type) { + this.fieldSignature = ref; this.tag = tag; this.methodSignature = null; this.type = type; @@ -110,7 +110,9 @@ public static boolean isMethodRef(int kind) { // FIXME: [ms] serialize in a way it can be restored with the same parameters; adapt Jimple.g4 and // JimpleConverter.java public String toString() { - return "handle: " + methodSignature; + return "handle: " + + (methodSignature == null ? "" : methodSignature) + + (fieldSignature == null ? "" : fieldSignature); } @Nonnull diff --git a/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java b/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java index 536a6619dfb..db76ca5dd91 100644 --- a/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java +++ b/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java @@ -1148,7 +1148,7 @@ private Immediate toSootValue(@Nonnull Object val) throws UnsupportedOperationEx } else { v = JavaJimple.getInstance() - .newMethodHandle(toSootFieldRef((Handle) val), ((Handle) val).getTag()); + .newMethodHandle(toSootFieldSignature((Handle) val), ((Handle) val).getTag()); } } else { throw new UnsupportedOperationException("Unknown constant type: " + val.getClass()); @@ -1172,6 +1172,13 @@ private JFieldRef toSootFieldRef(Handle methodHandle) { } } + private FieldSignature toSootFieldSignature(Handle methodHandle) { + String bsmClsName = AsmUtil.toQualifiedName(methodHandle.getOwner()); + JavaClassType bsmCls = identifierFactory.getClassType(bsmClsName); + Type t = AsmUtil.toJimpleSignatureDesc(methodHandle.getDesc()).get(0); + return identifierFactory.getFieldSignature(methodHandle.getName(), bsmCls, t); + } + private MethodSignature toMethodSignature(Handle methodHandle) { String bsmClsName = AsmUtil.toQualifiedName(methodHandle.getOwner()); JavaClassType bsmCls = identifierFactory.getClassType(bsmClsName); diff --git a/sootup.java.core/src/main/java/sootup/java/core/language/JavaJimple.java b/sootup.java.core/src/main/java/sootup/java/core/language/JavaJimple.java index 23bc6b44319..3ec7d04c4ca 100644 --- a/sootup.java.core/src/main/java/sootup/java/core/language/JavaJimple.java +++ b/sootup.java.core/src/main/java/sootup/java/core/language/JavaJimple.java @@ -32,7 +32,7 @@ import sootup.core.jimple.common.constant.MethodType; import sootup.core.jimple.common.constant.StringConstant; import sootup.core.jimple.common.ref.JCaughtExceptionRef; -import sootup.core.jimple.common.ref.JFieldRef; +import sootup.core.signatures.FieldSignature; import sootup.core.signatures.MethodSignature; import sootup.core.types.NullType; import sootup.core.types.PrimitiveType; @@ -86,7 +86,7 @@ public StringConstant newStringConstant(String value) { return new StringConstant(value, getIdentifierFactory().getType("java.lang.String")); } - public MethodHandle newMethodHandle(JFieldRef ref, int tag) { + public MethodHandle newMethodHandle(FieldSignature ref, int tag) { return new MethodHandle( ref, tag, getIdentifierFactory().getType("java.lang.invoke.MethodHandle")); } From 5e8fc4a2bd01d3d2b6d52d8b01ebda00939a093a Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 11 Aug 2023 17:53:34 +0200 Subject: [PATCH 06/36] added Test for Records in Java14 --- .../java14/binary/RecordTest.class | Bin 0 -> 1216 bytes .../java14/source/RecordTest.java | 6 +++ .../minimaltestsuite/java14/RecordTest.java | 51 ++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 shared-test-resources/miniTestSuite/java14/binary/RecordTest.class create mode 100644 shared-test-resources/miniTestSuite/java14/source/RecordTest.java create mode 100644 sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java14/RecordTest.java diff --git a/shared-test-resources/miniTestSuite/java14/binary/RecordTest.class b/shared-test-resources/miniTestSuite/java14/binary/RecordTest.class new file mode 100644 index 0000000000000000000000000000000000000000..f10d31483f04146a0c7febafc173050014f7935c GIT binary patch literal 1216 zcmaJ=U2hUW6g?Lx3%C@DZM9-ss;$DdminzheXzzzf*-M@5BfB~q-+bjxVtp*Klxx2 z8xtP<0sbiC9d?mLNFR3Y?A>$ExpVf;?>~cI0G{J%3K2v##B|IdPRJgMQ&H{+>!|!u zHf^Uxh(9we(|bXP7E6aoB#_jQ(s2noA?1VW()9==_^B$yyp9aA{MI1kYGcX+&oQl| zN{*#-Ixb_8knn6jODGg;W4cOdcHOd$E4a#aZQ-`}?Up2DChMw-{+fhR?qf9=Uv(rr3s&$FFy$$m$;Za5Kee4Zu=t4~Zp;8y~BY^SI+G6apEG(oRgmUM<1 z($(;gur)T}fv|!m|}YPEEfWVm0O*;~>61tNdk+-|nj`#W7?2 z1R42rXvWSt(r29Fzr$+|F%oo{I~dNk*8L>-bsV+p)oL#kbCpIBLd#^Z3qN zpGV26{Q_T!8yx=!F9F|Xfb+N+fD7D&I#I&d9$;k_nz*A8^(t2>!8zjxv}s}<+(tKYcfE4|9YfTa!Q;cX5wB1yZd30FUqlD}MpmfC1G2 literal 0 HcmV?d00001 diff --git a/shared-test-resources/miniTestSuite/java14/source/RecordTest.java b/shared-test-resources/miniTestSuite/java14/source/RecordTest.java new file mode 100644 index 00000000000..cc11333dcf5 --- /dev/null +++ b/shared-test-resources/miniTestSuite/java14/source/RecordTest.java @@ -0,0 +1,6 @@ +record RecordTest(int a, String b) { + public RecordTest(int a, String b) { + this.a = a; + this.b = b; + } +} \ No newline at end of file diff --git a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java14/RecordTest.java b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java14/RecordTest.java new file mode 100644 index 00000000000..154bd616084 --- /dev/null +++ b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java14/RecordTest.java @@ -0,0 +1,51 @@ +package sootup.java.bytecode.minimaltestsuite.java14; + +import categories.Java9Test; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import sootup.core.model.SootMethod; +import sootup.core.signatures.MethodSignature; +import sootup.java.bytecode.minimaltestsuite.MinimalBytecodeTestSuiteBase; +import sootup.java.core.JavaIdentifierFactory; +import sootup.java.core.types.JavaClassType; + +/** @author Jonas Klauke */ +@Category(Java9Test.class) +public class RecordTest extends MinimalBytecodeTestSuiteBase { + + @Override + public JavaClassType getDeclaredClassSignature() { + return JavaIdentifierFactory.getInstance().getClassType("RecordTest"); + } + + @Override + public MethodSignature getMethodSignature() { + System.out.println(getDeclaredClassSignature()); + return identifierFactory.getMethodSignature( + getDeclaredClassSignature(), + "equals", + "boolean", + Collections.singletonList("java.lang.Object")); + } + + @Override + public List expectedBodyStmts() { + return Stream.of( + "l0 := @this: RecordTest", + "l1 := @parameter0: java.lang.Object", + "$stack2 = dynamicinvoke \"equals\" (l0, l1) (class \"LRecordTest;\", \"a;b\", handle: , handle: )", + "return $stack2") + .collect(Collectors.toCollection(ArrayList::new)); + } + + @Test + public void test() { + SootMethod method = loadMethod(getMethodSignature()); + assertJimpleStmts(method, expectedBodyStmts()); + } +} From e544a578b8f6befa5b6b37d98fe1f71e4a99521a Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Mon, 14 Aug 2023 18:16:24 +0200 Subject: [PATCH 07/36] added the tag to the methodhandle serialization. Adapted the jimple parser to the new changes --- .../InstantiateClassValueVisitorTest.java | 12 +- .../jimple/common/constant/MethodHandle.java | 109 ++++++++++++------ .../minimaltestsuite/java14/RecordTest.java | 44 ++++++- .../sootup/java/core/language/JavaJimple.java | 12 +- .../src/main/antlr4/sootup/jimple/Jimple.g4 | 5 +- .../sootup/jimple/parser/JimpleConverter.java | 22 ++-- .../jimple/MethodAcceptingLamExpr.jimple | 2 +- .../resources/jimple/MethodReference.jimple | 2 +- .../java8/MethodAcceptingLamExprTest.java | 2 +- 9 files changed, 149 insertions(+), 61 deletions(-) diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/InstantiateClassValueVisitorTest.java b/sootup.callgraph/src/test/java/sootup/callgraph/InstantiateClassValueVisitorTest.java index 7186e18082e..2313bfaea48 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/InstantiateClassValueVisitorTest.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/InstantiateClassValueVisitorTest.java @@ -14,13 +14,10 @@ import sootup.core.jimple.basic.Local; import sootup.core.jimple.basic.Value; import sootup.core.jimple.common.constant.BooleanConstant; -import sootup.core.jimple.common.constant.ClassConstant; import sootup.core.jimple.common.constant.DoubleConstant; -import sootup.core.jimple.common.constant.EnumConstant; import sootup.core.jimple.common.constant.FloatConstant; import sootup.core.jimple.common.constant.IntConstant; import sootup.core.jimple.common.constant.LongConstant; -import sootup.core.jimple.common.constant.MethodHandle; import sootup.core.jimple.common.constant.MethodType; import sootup.core.jimple.common.constant.StringConstant; import sootup.core.jimple.common.expr.JAddExpr; @@ -70,6 +67,7 @@ import sootup.java.bytecode.inputlocation.JavaClassPathAnalysisInputLocation; import sootup.java.core.JavaProject; import sootup.java.core.JavaSootClass; +import sootup.java.core.language.JavaJimple; import sootup.java.core.language.JavaLanguage; @Category(Java8Test.class) @@ -153,10 +151,10 @@ private void fillList(List listWithAllValues, View view) { listWithAllValues.add(FloatConstant.getInstance(2.5f)); listWithAllValues.add(IntConstant.getInstance(3)); listWithAllValues.add(LongConstant.getInstance(3L)); - listWithAllValues.add(new StringConstant("String", StringClass)); - listWithAllValues.add(new EnumConstant("3", StringClass)); - listWithAllValues.add(new ClassConstant("java/lang/String", StringClass)); - listWithAllValues.add(new MethodHandle(toStringMethod, 3, StringClass)); + listWithAllValues.add(stringConstant); + listWithAllValues.add(JavaJimple.getInstance().newEnumConstant("3", "EnumTest")); + listWithAllValues.add(JavaJimple.getInstance().newClassConstant("java/lang/String")); + listWithAllValues.add(JavaJimple.getInstance().newMethodHandle(toStringMethod, 5)); listWithAllValues.add(new MethodType(toStringMethod.getSubSignature(), StringClass)); listWithAllValues.add(new JAddExpr(stringConstant, stringConstant)); listWithAllValues.add(new JAndExpr(stringConstant, stringConstant)); diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/constant/MethodHandle.java b/sootup.core/src/main/java/sootup/core/jimple/common/constant/MethodHandle.java index 58cfd51cd75..fd1792c29e4 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/constant/MethodHandle.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/constant/MethodHandle.java @@ -4,7 +4,7 @@ * #%L * Soot - a J*va Optimization Framework * %% - * Copyright (C) 2005-2020 Jennifer Lhotak, Andreas Dann, Linghui Luo and others + * Copyright (C) 2005-2023 Jennifer Lhotak, Andreas Dann, Linghui, Luo Jonas Klauke and others * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as @@ -26,11 +26,13 @@ import sootup.core.jimple.visitor.ConstantVisitor; import sootup.core.signatures.FieldSignature; import sootup.core.signatures.MethodSignature; +import sootup.core.signatures.SootClassMemberSignature; +import sootup.core.signatures.SootClassMemberSubSignature; import sootup.core.types.Type; public class MethodHandle implements Constant { - private final Type type; + @Nonnull private final Type type; public enum Kind { REF_GET_FIELD(1, "REF_GET_FIELD"), @@ -60,6 +62,10 @@ public int getValue() { return val; } + public String getValueName() { + return valStr; + } + public static Kind getKind(int kind) { for (Kind k : Kind.values()) { if (k.getValue() == kind) { @@ -69,50 +75,83 @@ public static Kind getKind(int kind) { throw new RuntimeException("Error: No method handle kind for value '" + kind + "'."); } - public static Kind getKind(String kind) { + public static Kind getKind(String kindName) { for (Kind k : Kind.values()) { - if (k.toString().equals(kind)) { + if (k.getValueName().equals(kindName)) { return k; } } - throw new RuntimeException("Error: No method handle kind for value '" + kind + "'."); + throw new RuntimeException("Error: No method handle kind for value name '" + kindName + "'."); } } - private final MethodSignature methodSignature; - private final FieldSignature fieldSignature; + @Nonnull + private final SootClassMemberSignature referenceSignature; - public int tag; + @Nonnull private final Kind kind; - public MethodHandle(MethodSignature methodSignature, int tag, Type type) { - this.methodSignature = methodSignature; - this.tag = tag; - this.fieldSignature = null; + public MethodHandle( + @Nonnull SootClassMemberSignature referenceSignature, + int tag, + @Nonnull Type type) { + this.kind = Kind.getKind(tag); this.type = type; + this.referenceSignature = referenceSignature; + if ((this.isMethodRef() && !(referenceSignature instanceof MethodSignature)) + || (this.isFieldRef() && !(referenceSignature instanceof FieldSignature))) { + throw new IllegalArgumentException( + "Tag:" + + tag + + " " + + kind.valStr + + " does not match with the given signature:" + + referenceSignature.getClass()); + } } - public MethodHandle(FieldSignature ref, int tag, Type type) { - this.fieldSignature = ref; - this.tag = tag; - this.methodSignature = null; + public MethodHandle( + @Nonnull SootClassMemberSignature referenceSignature, + @Nonnull MethodHandle.Kind kind, + @Nonnull Type type) { + this.kind = kind; this.type = type; + this.referenceSignature = referenceSignature; + if ((this.isMethodRef() && !(referenceSignature instanceof MethodSignature)) + || (this.isFieldRef() && !(referenceSignature instanceof FieldSignature))) { + throw new IllegalArgumentException( + "Kind:" + + kind.valStr + + " does not match with the given signature:" + + referenceSignature.getClass()); + } } - public static boolean isMethodRef(int kind) { - return kind == Kind.REF_INVOKE_VIRTUAL.getValue() - || kind == Kind.REF_INVOKE_STATIC.getValue() - || kind == Kind.REF_INVOKE_SPECIAL.getValue() - || kind == Kind.REF_INVOKE_CONSTRUCTOR.getValue() - || kind == Kind.REF_INVOKE_INTERFACE.getValue(); + public static boolean isMethodRef(int tag) { + return tag == Kind.REF_INVOKE_VIRTUAL.getValue() + || tag == Kind.REF_INVOKE_STATIC.getValue() + || tag == Kind.REF_INVOKE_SPECIAL.getValue() + || tag == Kind.REF_INVOKE_CONSTRUCTOR.getValue() + || tag == Kind.REF_INVOKE_INTERFACE.getValue(); + } + + public static boolean isFieldRef(int tag) { + return tag == Kind.REF_GET_FIELD.getValue() + || tag == Kind.REF_PUT_FIELD.getValue() + || tag == Kind.REF_PUT_FIELD_STATIC.getValue() + || tag == Kind.REF_GET_FIELD_STATIC.getValue(); + } + + public boolean isMethodRef() { + return MethodHandle.isMethodRef(this.kind.getValue()); + } + + public boolean isFieldRef() { + return MethodHandle.isFieldRef(this.kind.getValue()); } @Override - // FIXME: [ms] serialize in a way it can be restored with the same parameters; adapt Jimple.g4 and - // JimpleConverter.java public String toString() { - return "handle: " - + (methodSignature == null ? "" : methodSignature) - + (fieldSignature == null ? "" : fieldSignature); + return "methodhandle: \"" + kind.valStr + "\" " + referenceSignature; } @Nonnull @@ -121,8 +160,8 @@ public Type getType() { return type; } - public MethodSignature getMethodSignature() { - return methodSignature; + public SootClassMemberSignature getReferenceSignature() { + return referenceSignature; } @Override @@ -132,9 +171,9 @@ public void accept(@Nonnull ConstantVisitor v) { @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((methodSignature == null) ? 0 : methodSignature.hashCode()); + int result = type.hashCode(); + result = 31 * result + referenceSignature.hashCode(); + result = 31 * result + kind.hashCode(); return result; } @@ -150,10 +189,6 @@ public boolean equals(Object obj) { return false; } MethodHandle other = (MethodHandle) obj; - if (methodSignature == null) { - return other.methodSignature == null; - } else { - return methodSignature.equals(other.methodSignature); - } + return referenceSignature.equals(other.referenceSignature); } } diff --git a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java14/RecordTest.java b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java14/RecordTest.java index 154bd616084..c56e28548c9 100644 --- a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java14/RecordTest.java +++ b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java14/RecordTest.java @@ -1,5 +1,8 @@ package sootup.java.bytecode.minimaltestsuite.java14; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + import categories.Java9Test; import java.util.ArrayList; import java.util.Collections; @@ -8,10 +11,17 @@ import java.util.stream.Stream; import org.junit.Test; import org.junit.experimental.categories.Category; +import sootup.core.jimple.basic.Immediate; +import sootup.core.jimple.common.expr.JDynamicInvokeExpr; +import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.SootMethod; +import sootup.core.signatures.FieldSignature; import sootup.core.signatures.MethodSignature; +import sootup.core.signatures.PackageName; +import sootup.core.types.PrimitiveType; import sootup.java.bytecode.minimaltestsuite.MinimalBytecodeTestSuiteBase; import sootup.java.core.JavaIdentifierFactory; +import sootup.java.core.language.JavaJimple; import sootup.java.core.types.JavaClassType; /** @author Jonas Klauke */ @@ -38,7 +48,7 @@ public List expectedBodyStmts() { return Stream.of( "l0 := @this: RecordTest", "l1 := @parameter0: java.lang.Object", - "$stack2 = dynamicinvoke \"equals\" (l0, l1) (class \"LRecordTest;\", \"a;b\", handle: , handle: )", + "$stack2 = dynamicinvoke \"equals\" (l0, l1) (class \"LRecordTest;\", \"a;b\", methodhandle: \"REF_GET_FIELD\" , methodhandle: \"REF_GET_FIELD\" )", "return $stack2") .collect(Collectors.toCollection(ArrayList::new)); } @@ -47,5 +57,37 @@ public List expectedBodyStmts() { public void test() { SootMethod method = loadMethod(getMethodSignature()); assertJimpleStmts(method, expectedBodyStmts()); + List dynamicInvokes = + method.getBody().getStmts().stream() + .filter(Stmt::containsInvokeExpr) + .map(Stmt::getInvokeExpr) + .filter(abstractInvokeExpr -> abstractInvokeExpr instanceof JDynamicInvokeExpr) + .map(abstractInvokeExpr -> (JDynamicInvokeExpr) abstractInvokeExpr) + .collect(Collectors.toList()); + assertEquals(1, dynamicInvokes.size()); + JDynamicInvokeExpr invoke = dynamicInvokes.get(0); + + // test bootstrap args + List bootTrapArgs = invoke.getBootstrapArgs(); + assertTrue(bootTrapArgs.contains(JavaJimple.getInstance().newClassConstant("LRecordTest;"))); + assertTrue(bootTrapArgs.contains(JavaJimple.getInstance().newStringConstant("a;b"))); + assertTrue( + bootTrapArgs.contains( + JavaJimple.getInstance() + .newMethodHandle( + new FieldSignature( + new JavaClassType("RecordTest", new PackageName("")), + "a", + PrimitiveType.getInt()), + 1))); + assertTrue( + bootTrapArgs.contains( + JavaJimple.getInstance() + .newMethodHandle( + new FieldSignature( + new JavaClassType("RecordTest", new PackageName("")), + "b", + new JavaClassType("String", new PackageName("java.lang"))), + 1))); } } diff --git a/sootup.java.core/src/main/java/sootup/java/core/language/JavaJimple.java b/sootup.java.core/src/main/java/sootup/java/core/language/JavaJimple.java index 3ec7d04c4ca..5d238bf85b8 100644 --- a/sootup.java.core/src/main/java/sootup/java/core/language/JavaJimple.java +++ b/sootup.java.core/src/main/java/sootup/java/core/language/JavaJimple.java @@ -32,8 +32,8 @@ import sootup.core.jimple.common.constant.MethodType; import sootup.core.jimple.common.constant.StringConstant; import sootup.core.jimple.common.ref.JCaughtExceptionRef; -import sootup.core.signatures.FieldSignature; -import sootup.core.signatures.MethodSignature; +import sootup.core.signatures.SootClassMemberSignature; +import sootup.core.signatures.SootClassMemberSubSignature; import sootup.core.types.NullType; import sootup.core.types.PrimitiveType; import sootup.core.types.Type; @@ -86,14 +86,16 @@ public StringConstant newStringConstant(String value) { return new StringConstant(value, getIdentifierFactory().getType("java.lang.String")); } - public MethodHandle newMethodHandle(FieldSignature ref, int tag) { + public MethodHandle newMethodHandle( + SootClassMemberSignature ref, int tag) { return new MethodHandle( ref, tag, getIdentifierFactory().getType("java.lang.invoke.MethodHandle")); } - public MethodHandle newMethodHandle(MethodSignature ref, int tag) { + public MethodHandle newMethodHandle( + SootClassMemberSignature ref, MethodHandle.Kind kind) { return new MethodHandle( - ref, tag, getIdentifierFactory().getType("java.lang.invoke.MethodHandle")); + ref, kind, getIdentifierFactory().getType("java.lang.invoke.MethodHandle")); } public MethodType newMethodType(List parameterTypes, Type returnType) { diff --git a/sootup.jimple.parser/src/main/antlr4/sootup/jimple/Jimple.g4 b/sootup.jimple.parser/src/main/antlr4/sootup/jimple/Jimple.g4 index 31082f1cd23..ecfbf9debcb 100644 --- a/sootup.jimple.parser/src/main/antlr4/sootup/jimple/Jimple.g4 +++ b/sootup.jimple.parser/src/main/antlr4/sootup/jimple/Jimple.g4 @@ -280,6 +280,9 @@ grammar Jimple; /*local*/ local=identifier | /*constant*/ constant; + methodhandle: + 'methodhandle: ' STRING_CONSTANT (method_signature|field_signature); + constant : /*boolean*/ BOOL_CONSTANT | /*integer*/ integer_constant | @@ -287,7 +290,7 @@ grammar Jimple; /*string*/ STRING_CONSTANT | /*clazz*/ CLASS STRING_CONSTANT | /*null*/ NULL | - methodhandle='handle:' method_signature | + methodhandle | methodtype='methodtype:' method_subsignature ; binop : diff --git a/sootup.jimple.parser/src/main/java/sootup/jimple/parser/JimpleConverter.java b/sootup.jimple.parser/src/main/java/sootup/jimple/parser/JimpleConverter.java index 6dda6e812b3..66334b3caf0 100644 --- a/sootup.jimple.parser/src/main/java/sootup/jimple/parser/JimpleConverter.java +++ b/sootup.jimple.parser/src/main/java/sootup/jimple/parser/JimpleConverter.java @@ -23,6 +23,8 @@ import sootup.core.model.*; import sootup.core.signatures.FieldSignature; import sootup.core.signatures.MethodSignature; +import sootup.core.signatures.SootClassMemberSignature; +import sootup.core.signatures.SootClassMemberSubSignature; import sootup.core.transform.BodyInterceptor; import sootup.core.types.*; import sootup.java.core.JavaIdentifierFactory; @@ -696,13 +698,19 @@ public Constant visitConstant(JimpleParser.ConstantContext ctx) { return BooleanConstant.getInstance(firstChar == 't' || firstChar == 'T'); } else if (ctx.NULL() != null) { return NullConstant.getInstance(); - } else if (ctx.methodhandle != null && ctx.method_signature() != null) { - final MethodSignature methodSignature = - util.getMethodSignature(ctx.method_signature(), ctx); - // TODO: [ms] support handles with JFieldRef too - // FIXME: [ms] update/specify tag when its printed - // return JavaJimple.getInstance().newMethodHandle( , 0); - return JavaJimple.getInstance().newMethodHandle(methodSignature, 0); + } else if (ctx.methodhandle() != null) { + JimpleParser.MethodhandleContext methodhandleContext = ctx.methodhandle(); + final String kindName = methodhandleContext.STRING_CONSTANT().getText(); + final SootClassMemberSignature + referenceSignature = + (methodhandleContext.method_signature() != null) + ? util.getMethodSignature( + methodhandleContext.method_signature(), methodhandleContext) + : util.getFieldSignature(methodhandleContext.field_signature()); + return JavaJimple.getInstance() + .newMethodHandle( + referenceSignature, + MethodHandle.Kind.getKind(kindName.substring(1, kindName.length() - 1))); } else if (ctx.methodtype != null && ctx.method_subsignature() != null) { final JimpleParser.Type_listContext typelist = ctx.method_subsignature().type_list(); final List typeList = util.getTypeList(typelist); diff --git a/sootup.jimple.parser/src/test/java/resources/jimple/MethodAcceptingLamExpr.jimple b/sootup.jimple.parser/src/test/java/resources/jimple/MethodAcceptingLamExpr.jimple index edace00f545..e2c37e9db00 100644 --- a/sootup.jimple.parser/src/test/java/resources/jimple/MethodAcceptingLamExpr.jimple +++ b/sootup.jimple.parser/src/test/java/resources/jimple/MethodAcceptingLamExpr.jimple @@ -19,7 +19,7 @@ public super class MethodAcceptingLamExpr extends java.lang.Object l0 := @this: MethodAcceptingLamExpr; - $stack2 = dynamicinvoke "calcPercentage" () (methodtype: double __METHODTYPE__(double), handle: , methodtype: double __METHODTYPE__(double)); + $stack2 = dynamicinvoke "calcPercentage" () (methodtype: double __METHODTYPE__(double), methodhandle: "REF_INVOKE_STATIC" , methodtype: double __METHODTYPE__(double)); l1 = $stack2; diff --git a/sootup.jimple.parser/src/test/java/resources/jimple/MethodReference.jimple b/sootup.jimple.parser/src/test/java/resources/jimple/MethodReference.jimple index e433a96e522..33aeb4fc0ff 100644 --- a/sootup.jimple.parser/src/test/java/resources/jimple/MethodReference.jimple +++ b/sootup.jimple.parser/src/test/java/resources/jimple/MethodReference.jimple @@ -41,7 +41,7 @@ public super class MethodReference extends java.lang.Object $stack4 = staticinvoke (l1); - $stack5 = dynamicinvoke "display" (l1) (methodtype: void __METHODTYPE__(), handle: , methodtype: void __METHODTYPE__()); + $stack5 = dynamicinvoke "display" (l1) (methodtype: void __METHODTYPE__(), methodhandle: "REF_INVOKE_VIRTUAL" , methodtype: void __METHODTYPE__()); l2 = $stack5; diff --git a/sootup.jimple.parser/src/test/java/sootup/jimple/parser/javatestsuite/java8/MethodAcceptingLamExprTest.java b/sootup.jimple.parser/src/test/java/sootup/jimple/parser/javatestsuite/java8/MethodAcceptingLamExprTest.java index 3710d168925..fd4e0f5269d 100644 --- a/sootup.jimple.parser/src/test/java/sootup/jimple/parser/javatestsuite/java8/MethodAcceptingLamExprTest.java +++ b/sootup.jimple.parser/src/test/java/sootup/jimple/parser/javatestsuite/java8/MethodAcceptingLamExprTest.java @@ -30,7 +30,7 @@ public void test() { public List expectedBodyStmts() { return Stream.of( "l0 := @this: MethodAcceptingLamExpr", - "$stack2 = dynamicinvoke \"calcPercentage\" () (methodtype: double __METHODTYPE__(double), handle: , methodtype: double __METHODTYPE__(double))", + "$stack2 = dynamicinvoke \"calcPercentage\" () (methodtype: double __METHODTYPE__(double), methodhandle: \"REF_INVOKE_STATIC\" , methodtype: double __METHODTYPE__(double))", "l1 = $stack2", "$stack4 = ", "$stack3 = new java.lang.StringBuilder", From 859304efe89dd3541453fb0f17646605cff50cd2 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Mon, 14 Aug 2023 18:29:39 +0200 Subject: [PATCH 08/36] Adapted bytecode testcases to new methodhandle serialization --- .../minimaltestsuite/java11/TypeInferenceLambdaTest.java | 2 +- .../minimaltestsuite/java8/MethodAcceptingLamExprTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java11/TypeInferenceLambdaTest.java b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java11/TypeInferenceLambdaTest.java index f640bfc4714..454822e66e8 100644 --- a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java11/TypeInferenceLambdaTest.java +++ b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java11/TypeInferenceLambdaTest.java @@ -33,7 +33,7 @@ public MethodSignature getMethodSignature() { public List expectedBodyStmts() { return Stream.of( "l0 := @this: TypeInferenceLambda", - "l1 = dynamicinvoke \"apply\" () (methodtype: java.lang.Object __METHODTYPE__(java.lang.Object,java.lang.Object), handle: , methodtype: java.lang.Integer __METHODTYPE__(java.lang.Integer,java.lang.Integer))", + "l1 = dynamicinvoke \"apply\" () (methodtype: java.lang.Object __METHODTYPE__(java.lang.Object,java.lang.Object), methodhandle: \"REF_INVOKE_STATIC\" , methodtype: java.lang.Integer __METHODTYPE__(java.lang.Integer,java.lang.Integer))", "$stack4 = staticinvoke (2)", "$stack3 = staticinvoke (3)", "$stack5 = interfaceinvoke l1.($stack4, $stack3)", diff --git a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java8/MethodAcceptingLamExprTest.java b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java8/MethodAcceptingLamExprTest.java index 9042cd14b7d..7901fb7612d 100644 --- a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java8/MethodAcceptingLamExprTest.java +++ b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java8/MethodAcceptingLamExprTest.java @@ -43,7 +43,7 @@ public void test() { public List expectedBodyStmts() { return Stream.of( "l0 := @this: MethodAcceptingLamExpr", - "l1 = dynamicinvoke \"calcPercentage\" () (methodtype: double __METHODTYPE__(double), handle: , methodtype: double __METHODTYPE__(double))", + "l1 = dynamicinvoke \"calcPercentage\" () (methodtype: double __METHODTYPE__(double), methodhandle: \"REF_INVOKE_STATIC\" , methodtype: double __METHODTYPE__(double))", "$stack3 = ", "$stack2 = new java.lang.StringBuilder", "specialinvoke $stack2.()>()", From d13cc919a98e9f5be31b31546f3ede075cabfadf Mon Sep 17 00:00:00 2001 From: Markus Schmidt Date: Mon, 14 Aug 2023 22:42:50 +0200 Subject: [PATCH 09/36] fix annotations --- .../src/test/java/sootup/java/bytecode/Soot1577.java | 7 ++++++- .../src/test/java/sootup/java/bytecode/Soot1580.java | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/Soot1577.java b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/Soot1577.java index 5e76875a2fa..56bb29a92d2 100644 --- a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/Soot1577.java +++ b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/Soot1577.java @@ -1,7 +1,10 @@ package sootup.java.bytecode; +import categories.Java8Test; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; +import org.junit.experimental.categories.Category; import sootup.core.inputlocation.AnalysisInputLocation; import sootup.core.model.SootMethod; import sootup.java.bytecode.inputlocation.JavaClassPathAnalysisInputLocation; @@ -10,16 +13,18 @@ import sootup.java.core.language.JavaLanguage; import sootup.java.core.views.JavaView; +@Category(Java8Test.class) public class Soot1577 { final String directory = "../shared-test-resources/soot-1577/"; @Test + @Ignore("conversion fails - could be a dex2jar conversion problem") public void test() { AnalysisInputLocation inputLocation = new JavaClassPathAnalysisInputLocation(directory); JavaProject project = - JavaProject.builder(new JavaLanguage(7)).addInputLocation(inputLocation).build(); + JavaProject.builder(new JavaLanguage(8)).addInputLocation(inputLocation).build(); JavaView view = project.createView(); diff --git a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/Soot1580.java b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/Soot1580.java index 9cecd0aa910..0d5555d72ec 100644 --- a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/Soot1580.java +++ b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/Soot1580.java @@ -1,9 +1,11 @@ package sootup.java.bytecode; +import categories.Java8Test; import java.nio.file.Path; import java.nio.file.Paths; import org.junit.Assert; import org.junit.Test; +import org.junit.experimental.categories.Category; import sootup.core.inputlocation.AnalysisInputLocation; import sootup.core.model.SootMethod; import sootup.core.types.ClassType; @@ -15,6 +17,7 @@ import sootup.java.core.language.JavaLanguage; import sootup.java.core.views.JavaView; +@Category(Java8Test.class) public class Soot1580 { final Path jar = Paths.get("../shared-test-resources/soot-1580/jpush-android_v3.0.5.jar"); From 03b20238b96fafa5b7f4c09a2ec6583239165e4f Mon Sep 17 00:00:00 2001 From: Markus Schmidt Date: Mon, 14 Aug 2023 22:44:20 +0200 Subject: [PATCH 10/36] add proposed indy testcase - rhs is null --- shared-test-resources/bugfixes/Indy.java | 15 ++++++++++ .../core/jimple/common/stmt/JAssignStmt.java | 4 ++- .../java/sootup/java/bytecode/IndyTests.java | 30 +++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 shared-test-resources/bugfixes/Indy.java create mode 100644 sootup.java.bytecode/src/test/java/sootup/java/bytecode/IndyTests.java diff --git a/shared-test-resources/bugfixes/Indy.java b/shared-test-resources/bugfixes/Indy.java new file mode 100644 index 00000000000..800203ab873 --- /dev/null +++ b/shared-test-resources/bugfixes/Indy.java @@ -0,0 +1,15 @@ +import java.time.LocalDate; +import java.time.Period; +import java.util.stream.LongStream; +import java.util.stream.Stream; +class Indy{ + public Stream test(LocalDate endExclusive, Period step) { + long months = step.toTotalMonths(); + long days = step.getDays(); + int sign = months > 0 || days > 0 ? 1 : -1; + long steps = 200000 / (months + days); + return LongStream.rangeClosed(0, steps).mapToObj( + n -> endExclusive.plusDays(days * n)); + } + +} \ No newline at end of file diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java index 389f13edb12..01e871d4abe 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java @@ -53,7 +53,9 @@ public JAssignStmt( } if (!validateValue(rValue)) { throw new RuntimeException( - "Illegal Assignment statement. Make sure that right hand side has a valid operand."); + "Illegal Assignment statement. Make sure that right hand side (" + + rValue + + ") has a valid operand."); } } diff --git a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/IndyTests.java b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/IndyTests.java new file mode 100644 index 00000000000..f1ced45cb93 --- /dev/null +++ b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/IndyTests.java @@ -0,0 +1,30 @@ +package sootup.java.bytecode; + +import org.junit.Assert; +import org.junit.Test; +import sootup.core.inputlocation.AnalysisInputLocation; +import sootup.core.model.SootMethod; +import sootup.java.bytecode.inputlocation.JavaClassPathAnalysisInputLocation; +import sootup.java.core.JavaProject; +import sootup.java.core.JavaSootClass; +import sootup.java.core.language.JavaLanguage; +import sootup.java.core.views.JavaView; + +/** InvokeDynamics and the Operand stack.. */ +public class IndyTests { + final String directory = "../shared-test-resources/misc/"; + + @Test + public void test() { + AnalysisInputLocation inputLocation = + new JavaClassPathAnalysisInputLocation(directory); + + JavaProject project = + JavaProject.builder(new JavaLanguage(8)).addInputLocation(inputLocation).build(); + + JavaView view = project.createView(); + Assert.assertEquals(1, view.getClasses().size()); + + view.getClasses().stream().findFirst().get().getMethods().forEach(SootMethod::getBody); + } +} From 6bf2fb7ae0dc0d936c6075c03164347b8cd058d2 Mon Sep 17 00:00:00 2001 From: Markus Schmidt Date: Mon, 14 Aug 2023 22:54:44 +0200 Subject: [PATCH 11/36] fix errmsg and directory --- .../main/java/sootup/core/jimple/common/stmt/JAssignStmt.java | 2 +- .../src/test/java/sootup/java/bytecode/IndyTests.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java index 01e871d4abe..865223653cb 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java @@ -55,7 +55,7 @@ public JAssignStmt( throw new RuntimeException( "Illegal Assignment statement. Make sure that right hand side (" + rValue - + ") has a valid operand."); + + ") is a valid operand."); } } diff --git a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/IndyTests.java b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/IndyTests.java index f1ced45cb93..45fb8cd0e82 100644 --- a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/IndyTests.java +++ b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/IndyTests.java @@ -12,7 +12,7 @@ /** InvokeDynamics and the Operand stack.. */ public class IndyTests { - final String directory = "../shared-test-resources/misc/"; + final String directory = "../shared-test-resources/bugfixes/"; @Test public void test() { From 1472cb74ea15fdd5e7b00888a6a52c9863486fdb Mon Sep 17 00:00:00 2001 From: Markus Schmidt Date: Tue, 15 Aug 2023 09:24:10 +0200 Subject: [PATCH 12/36] add missing annotation --- .../src/test/java/sootup/java/bytecode/IndyTests.java | 3 +++ .../minimaltestsuite/java14/SwitchExprWithYieldTest.java | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/IndyTests.java b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/IndyTests.java index 45fb8cd0e82..c0cc8ba5e63 100644 --- a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/IndyTests.java +++ b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/IndyTests.java @@ -1,7 +1,9 @@ package sootup.java.bytecode; +import categories.Java9Test; import org.junit.Assert; import org.junit.Test; +import org.junit.experimental.categories.Category; import sootup.core.inputlocation.AnalysisInputLocation; import sootup.core.model.SootMethod; import sootup.java.bytecode.inputlocation.JavaClassPathAnalysisInputLocation; @@ -11,6 +13,7 @@ import sootup.java.core.views.JavaView; /** InvokeDynamics and the Operand stack.. */ +@Category(Java9Test.class) public class IndyTests { final String directory = "../shared-test-resources/bugfixes/"; diff --git a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java14/SwitchExprWithYieldTest.java b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java14/SwitchExprWithYieldTest.java index a0c7f2a48fe..f03a07a699a 100644 --- a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java14/SwitchExprWithYieldTest.java +++ b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java14/SwitchExprWithYieldTest.java @@ -25,7 +25,6 @@ public JavaClassType getDeclaredClassSignature() { @Override public MethodSignature getMethodSignature() { - System.out.println(getDeclaredClassSignature()); return identifierFactory.getMethodSignature( getDeclaredClassSignature(), "switchSomething", "void", Collections.emptyList()); } From c4297293b00bd642a8f4fa627c19456c83937ce0 Mon Sep 17 00:00:00 2001 From: Markus Schmidt Date: Tue, 15 Aug 2023 10:27:28 +0200 Subject: [PATCH 13/36] simplified test input; add missing .class --- shared-test-resources/bugfixes/Indy.class | Bin 0 -> 1064 bytes shared-test-resources/bugfixes/Indy.java | 18 +++++++++--------- 2 files changed, 9 insertions(+), 9 deletions(-) create mode 100644 shared-test-resources/bugfixes/Indy.class diff --git a/shared-test-resources/bugfixes/Indy.class b/shared-test-resources/bugfixes/Indy.class new file mode 100644 index 0000000000000000000000000000000000000000..1b83ecee8411bf2eeb26e8c39f3437f23313f6e7 GIT binary patch literal 1064 zcmbVL%Wl&^6g?A%m^cmzg#rzvKuKvHPy@>bkRTEwQc96hy6B2YGA(YLv1N}d<7hFp;%!0Xc^95kKaR$K|23 zGdL1M#gKdIN>@E+FzSuH0xlwN!m?3-%}`0)W952Iq(Z?bPFJdaA~9HQ^p=O*^MscK z?=KPMB^xD_$;gAio4$z1pJAik=$#=Q#B!)yUuvv(l84isK!jZRVOz5=*|>tM1UTUV zL#O^vfob?Z6K$Kg#*ppG(Ud+NekQVv}M0T$BD*uL+vT>S9+~k6CkYhZr;TzyX5}EfW~7lT@WI)0*a2urDMq z+@M>VXZH#!Bx~0#0?-i4trM6GA7QjkQ3OtKIfKt+$Rwe9Wuf00MF rRdPruE9K_(*BJjTi|FGdj} literal 0 HcmV?d00001 diff --git a/shared-test-resources/bugfixes/Indy.java b/shared-test-resources/bugfixes/Indy.java index 800203ab873..2143e237efe 100644 --- a/shared-test-resources/bugfixes/Indy.java +++ b/shared-test-resources/bugfixes/Indy.java @@ -1,15 +1,15 @@ import java.time.LocalDate; import java.time.Period; -import java.util.stream.LongStream; import java.util.stream.Stream; +import java.util.stream.IntStream; + +/** conversion failed when there is a merge (here: after the if) and an invokedynamic followed */ class Indy{ - public Stream test(LocalDate endExclusive, Period step) { - long months = step.toTotalMonths(); - long days = step.getDays(); - int sign = months > 0 || days > 0 ? 1 : -1; - long steps = 200000 / (months + days); - return LongStream.rangeClosed(0, steps).mapToObj( - n -> endExclusive.plusDays(days * n)); + public IntStream test(IntStream s) { + int sign; + if (s.isParallel()) { + sign = 1; + } + return s.map(n -> n+42); } - } \ No newline at end of file From bc74bf541c3797656d5e75dc77b6dd5248357ece Mon Sep 17 00:00:00 2001 From: Markus Schmidt Date: Tue, 15 Aug 2023 10:36:20 +0200 Subject: [PATCH 14/36] that input was too simple.. --- shared-test-resources/bugfixes/Indy.class | Bin 1064 -> 1083 bytes shared-test-resources/bugfixes/Indy.java | 2 ++ 2 files changed, 2 insertions(+) diff --git a/shared-test-resources/bugfixes/Indy.class b/shared-test-resources/bugfixes/Indy.class index 1b83ecee8411bf2eeb26e8c39f3437f23313f6e7..4e5ccd49f98348a241eed9f6fb7e62fc4b6d4c33 100644 GIT binary patch delta 110 zcmWN`y%B;?5Jlm$`*7X^Mow1inHy84KK`uXk57IIPBbE$7b4T?dda8Dz5Ws5 B4hjGO delta 75 zcmdnZv4Uem2eSej10#bZgA|YyXJBBkVqgM71_n{>oeb=Z3^N&+C$DD~72yI4axic* Ya5G2)rI{HRIVV41)?(zI%+I0&0CvC$JOBUy diff --git a/shared-test-resources/bugfixes/Indy.java b/shared-test-resources/bugfixes/Indy.java index 2143e237efe..98441621cd4 100644 --- a/shared-test-resources/bugfixes/Indy.java +++ b/shared-test-resources/bugfixes/Indy.java @@ -9,6 +9,8 @@ public IntStream test(IntStream s) { int sign; if (s.isParallel()) { sign = 1; + }else{ + sign = -1; } return s.map(n -> n+42); } From a12a41dfcd231e4425899433e564b1932620ec59 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 18 Aug 2023 12:16:37 +0200 Subject: [PATCH 15/36] fixed extension checking in the analysis location --- .../java-miniapps/MiniApp.jar | Bin 4316 -> 4475 bytes .../java-miniapps/src/junkclass | 1 + .../requires_exports/jar/modb.jar | Bin 1074 -> 1243 bytes .../requires_exports/src/modb/pkgb/junkclass | 1 + .../sootup/core/inputlocation/FileType.java | 5 +++ .../main/java/sootup/core/util/PathUtils.java | 2 +- .../JrtFileSystemAnalysisInputLocation.java | 32 ++++++++---------- .../PathBasedAnalysisInputLocation.java | 12 ++++--- .../AnalysisInputLocationTest.java | 9 ++--- .../PathBasedAnalysisInputLocationTest.java | 8 ++--- 10 files changed, 35 insertions(+), 35 deletions(-) create mode 100644 shared-test-resources/java-miniapps/src/junkclass create mode 100644 shared-test-resources/jigsaw-examples/requires_exports/src/modb/pkgb/junkclass diff --git a/shared-test-resources/java-miniapps/MiniApp.jar b/shared-test-resources/java-miniapps/MiniApp.jar index bb7ebf378d97a9b8379ef5939d265c49e513ea0c..a8f33af1e9217117ca71af9ddf811ca2028775e7 100644 GIT binary patch delta 189 zcmcbk_*-d1FkcEYiwFY;2M0q=xKKC)65s@~vr6-_lXDV_i+K+@ay1wTFdta|B>VKN zTL~Kziavd{@>$kXuUKNRr6cD{O8kX}ruMz(qxJcxTwMKzKfs%vLv8yuaYLXfW(=GC s`6`*b8JR>F5OyJC85lrzAwVD>lFb3$tZX1DZXjI4#K5o|eGoO%W* diff --git a/shared-test-resources/java-miniapps/src/junkclass b/shared-test-resources/java-miniapps/src/junkclass new file mode 100644 index 00000000000..e3bc908497b --- /dev/null +++ b/shared-test-resources/java-miniapps/src/junkclass @@ -0,0 +1 @@ +this is a test file to check if it recognized as class \ No newline at end of file diff --git a/shared-test-resources/jigsaw-examples/requires_exports/jar/modb.jar b/shared-test-resources/jigsaw-examples/requires_exports/jar/modb.jar index 3079df5844ceca92eea3e410699dae387217ecba..154aa390259fc423b67199306763c83d9b9c5536 100644 GIT binary patch delta 322 zcmdnQahr3(Q7$e91`Y;>mPn!S&8rx_8S9x@L>M?YI2dxmg~Az-03VQDke!~SpH-Td zot%?cT+DmOk*mQ#fce1sC)uZG-AdS)Q1t1mmCv%Cdc_ihEgd;uQsOT(G_~(NAFaKl$`~lwV9BSLQi5miqG6UiOZ03m)*9{>OV delta 145 zcmcc3xrt-K(TOZ#ljk!X=3!>xVqoB4VAva3;=l2{H{;|a=6ZDz1`!4h4i1KEDW(42 ztv-Tt7#J8X1F;|wBf!DQ3z$R%0=yZSxEK(IOn%EO#WaU;GAE0n+I~g`hJx($Bz-5n Yb%7 diff --git a/shared-test-resources/jigsaw-examples/requires_exports/src/modb/pkgb/junkclass b/shared-test-resources/jigsaw-examples/requires_exports/src/modb/pkgb/junkclass new file mode 100644 index 00000000000..e3bc908497b --- /dev/null +++ b/shared-test-resources/jigsaw-examples/requires_exports/src/modb/pkgb/junkclass @@ -0,0 +1 @@ +this is a test file to check if it recognized as class \ No newline at end of file diff --git a/sootup.core/src/main/java/sootup/core/inputlocation/FileType.java b/sootup.core/src/main/java/sootup/core/inputlocation/FileType.java index 06e5f3c9852..67fb9267614 100644 --- a/sootup.core/src/main/java/sootup/core/inputlocation/FileType.java +++ b/sootup.core/src/main/java/sootup/core/inputlocation/FileType.java @@ -47,6 +47,11 @@ public enum FileType { this.extension = fileExtension; } + @Nonnull + public String getExtensionWithDot() { + return "." + extension; + } + @Nonnull public String getExtension() { return extension; diff --git a/sootup.core/src/main/java/sootup/core/util/PathUtils.java b/sootup.core/src/main/java/sootup/core/util/PathUtils.java index 2253e4d7c39..613f2e3088a 100644 --- a/sootup.core/src/main/java/sootup/core/util/PathUtils.java +++ b/sootup.core/src/main/java/sootup/core/util/PathUtils.java @@ -60,7 +60,7 @@ public static boolean hasExtension(@Nonnull Path path, @Nonnull Collection> getClassSource( Path filepath = theFileSystem.getPath( klassType.getFullyQualifiedName().replace('.', '/') - + "." - + classProvider.getHandledFileType().getExtension()); + + classProvider.getHandledFileType().getExtensionWithDot()); // parse as module if (klassType.getPackageName() instanceof ModulePackageName) { @@ -136,8 +134,7 @@ protected Stream> getClassSourcesInternal( String moduleInfoFilename = JavaModuleIdentifierFactory.MODULE_INFO_FILE - + "." - + classProvider.getHandledFileType().getExtension(); + + classProvider.getHandledFileType().getExtensionWithDot(); final Path archiveRoot = theFileSystem.getPath("modules", moduleSignature.getModuleName()); try { @@ -148,20 +145,19 @@ protected Stream> getClassSourcesInternal( !Files.isDirectory(filePath) && filePath .toString() - .endsWith(classProvider.getHandledFileType().getExtension()) + .endsWith(classProvider.getHandledFileType().getExtensionWithDot()) && !filePath.toString().endsWith(moduleInfoFilename)) .flatMap( - p -> { - return StreamUtils.optionalToStream( - Optional.of( - classProvider.createClassSource( - this, - p, - this.fromPath( - p.subpath(2, p.getNameCount()), - p.subpath(1, 2), - identifierFactory)))); - }); + p -> + StreamUtils.optionalToStream( + Optional.of( + classProvider.createClassSource( + this, + p, + this.fromPath( + p.subpath(2, p.getNameCount()), + p.subpath(1, 2), + identifierFactory))))); } catch (IOException e) { throw new ResolveException("Error loading module " + moduleSignature, archiveRoot, e); } @@ -246,7 +242,7 @@ public Set getModules(View view) { return Collections.unmodifiableSet(moduleInfoMap.keySet()); } - @Nullable + @Nonnull @Override public SourceType getSourceType() { return sourceType; diff --git a/sootup.java.bytecode/src/main/java/sootup/java/bytecode/inputlocation/PathBasedAnalysisInputLocation.java b/sootup.java.bytecode/src/main/java/sootup/java/bytecode/inputlocation/PathBasedAnalysisInputLocation.java index 8c7b8ace543..262fe3cbbbc 100644 --- a/sootup.java.bytecode/src/main/java/sootup/java/bytecode/inputlocation/PathBasedAnalysisInputLocation.java +++ b/sootup.java.bytecode/src/main/java/sootup/java/bytecode/inputlocation/PathBasedAnalysisInputLocation.java @@ -177,8 +177,7 @@ protected Optional> getClassSourceI path.getFileSystem() .getPath( signature.getFullyQualifiedName().replace('.', '/') - + "." - + classProvider.getHandledFileType().getExtension())); + + classProvider.getHandledFileType().getExtensionWithDot())); if (!Files.exists(pathToClass)) { return Optional.empty(); @@ -653,7 +652,8 @@ protected void extractWarFile(Path warFilePath, final Path destDirectory) { dest.deleteOnExit(); } - ZipInputStream zis = new ZipInputStream(new FileInputStream(warFilePath.toString())); + ZipInputStream zis = + new ZipInputStream(Files.newInputStream(Paths.get(warFilePath.toString()))); ZipEntry zipEntry; while ((zipEntry = zis.getNextEntry()) != null) { Path filepath = destDirectory.resolve(zipEntry.getName()); @@ -668,7 +668,8 @@ protected void extractWarFile(Path warFilePath, final Path destDirectory) { if (file.exists()) { // compare contents -> does it contain the extracted war already? int readBytesExistingFile; - final BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); + final BufferedInputStream bis = + new BufferedInputStream(Files.newInputStream(file.toPath())); byte[] bisBuf = new byte[4096]; while ((readBytesZip = zis.read(incomingValues)) != -1) { if (extractedSize > maxAllowedBytesToExtract) { @@ -693,7 +694,8 @@ protected void extractWarFile(Path warFilePath, final Path destDirectory) { } } else { - BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); + BufferedOutputStream bos = + new BufferedOutputStream(Files.newOutputStream(file.toPath())); while ((readBytesZip = zis.read(incomingValues)) != -1) { if (extractedSize > maxAllowedBytesToExtract) { throw new RuntimeException( diff --git a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/AnalysisInputLocationTest.java b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/AnalysisInputLocationTest.java index e29df69cd36..dab4fe1236c 100644 --- a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/AnalysisInputLocationTest.java +++ b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/AnalysisInputLocationTest.java @@ -8,10 +8,8 @@ import java.util.Optional; import sootup.core.IdentifierFactory; import sootup.core.frontend.AbstractClassSource; -import sootup.core.frontend.ClassProvider; import sootup.core.inputlocation.AnalysisInputLocation; import sootup.core.types.ClassType; -import sootup.java.bytecode.frontend.AsmJavaClassProvider; import sootup.java.core.JavaIdentifierFactory; import sootup.java.core.JavaProject; import sootup.java.core.JavaSootClass; @@ -52,19 +50,16 @@ public abstract class AnalysisInputLocationTest { final Path mmrj = Paths.get("../shared-test-resources/multi-release-jar-modular/mrjar.jar"); final Path apk = Paths.get("../shared-test-resources/apk/SimpleApk.apk"); - private ClassProvider classProvider; - protected IdentifierFactory getIdentifierFactory() { return JavaIdentifierFactory.getInstance(); } protected void testClassReceival( - AnalysisInputLocation ns, ClassType sig, int minClassesFound) { + AnalysisInputLocation ns, ClassType sig, int classesFound) { final JavaProject project = JavaProject.builder(new JavaLanguage(8)).addInputLocation(ns).build(); final JavaView view = project.createView(); - classProvider = new AsmJavaClassProvider(view); final Optional> clazzOpt = ns.getClassSource(sig, view); @@ -73,6 +68,6 @@ protected void testClassReceival( final Collection> classSources = ns.getClassSources(view); - assertTrue(classSources.size() >= minClassesFound); + assertEquals(classSources.size(), classesFound); } } diff --git a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/PathBasedAnalysisInputLocationTest.java b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/PathBasedAnalysisInputLocationTest.java index 6830c69b2a1..273bd2be66e 100644 --- a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/PathBasedAnalysisInputLocationTest.java +++ b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/PathBasedAnalysisInputLocationTest.java @@ -273,7 +273,7 @@ public void testApk() { PathBasedAnalysisInputLocation.create(apk, null); final ClassType mainClass = getIdentifierFactory().getClassType("de.upb.futuresoot.fields.MainActivity"); - testClassReceival(pathBasedNamespace, mainClass, 1); + testClassReceival(pathBasedNamespace, mainClass, 1392); } @Test @@ -283,8 +283,8 @@ public void testJar() { final ClassType class1 = getIdentifierFactory().getClassType("Employee", "ds"); final ClassType mainClass = getIdentifierFactory().getClassType("MiniApp"); - testClassReceival(pathBasedNamespace, class1, 4); - testClassReceival(pathBasedNamespace, mainClass, 4); + testClassReceival(pathBasedNamespace, class1, 6); + testClassReceival(pathBasedNamespace, mainClass, 6); } @Test @@ -292,7 +292,7 @@ public void testWar() { PathBasedAnalysisInputLocation pathBasedNamespace = PathBasedAnalysisInputLocation.create(war, null); final ClassType warClass1 = getIdentifierFactory().getClassType("SimpleWarRead"); - testClassReceival(pathBasedNamespace, warClass1, 2); + testClassReceival(pathBasedNamespace, warClass1, 19); } @Test From 6b59bbf052505b67e8f9969d945e0f44ada6790c Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 18 Aug 2023 14:17:57 +0200 Subject: [PATCH 16/36] fixed extension checking in the analysis location and added handling of source resolve errors --- .../java-miniapps/MiniApp.jar | Bin 4475 -> 4612 bytes .../java-miniapps/src/NoClass.class | 1 + .../wala-tests/FakeJava.java | 1 + .../sootup/core/frontend/ClassProvider.java | 6 ++-- .../frontend/AsmJavaClassProvider.java | 33 +++++++++++------- .../JrtFileSystemAnalysisInputLocation.java | 19 +++++----- .../PathBasedAnalysisInputLocation.java | 5 ++- .../AnalysisInputLocationTest.java | 14 ++++---- .../PathBasedAnalysisInputLocationTest.java | 13 +++---- .../frontend/WalaJavaClassProvider.java | 4 +-- .../JavaSourcePathAnalysisInputLocation.java | 2 +- .../frontend/WalaJavaClassProviderTest.java | 14 +++++++- .../parser/JimpleAnalysisInputLocation.java | 5 ++- .../jimple/parser/JimpleClassProvider.java | 24 ++++++++++--- .../java/resources/jimple/FakeJimple.jimple | 1 + .../JimpleAnalysisInputLocationTest.java | 25 +++++++++++++ 16 files changed, 115 insertions(+), 52 deletions(-) create mode 100644 shared-test-resources/java-miniapps/src/NoClass.class create mode 100644 shared-test-resources/wala-tests/FakeJava.java create mode 100644 sootup.jimple.parser/src/test/java/resources/jimple/FakeJimple.jimple diff --git a/shared-test-resources/java-miniapps/MiniApp.jar b/shared-test-resources/java-miniapps/MiniApp.jar index a8f33af1e9217117ca71af9ddf811ca2028775e7..64f7fb6d76194ce5a8391ea934a2d2577262902d 100644 GIT binary patch delta 166 zcmeyZ)S|LsH=idniwFY;2M2>|u247w65s{0{qmi25{rxVl0hW*$rCzZ42$;s5o&d5 zeKP0Bqa=m^Z*~s#S@pYxfog>}Z{yp@3v#@_~2&l=%i? diff --git a/shared-test-resources/java-miniapps/src/NoClass.class b/shared-test-resources/java-miniapps/src/NoClass.class new file mode 100644 index 00000000000..b8e300dcb2c --- /dev/null +++ b/shared-test-resources/java-miniapps/src/NoClass.class @@ -0,0 +1 @@ +This is not a class \ No newline at end of file diff --git a/shared-test-resources/wala-tests/FakeJava.java b/shared-test-resources/wala-tests/FakeJava.java new file mode 100644 index 00000000000..69d3f89baec --- /dev/null +++ b/shared-test-resources/wala-tests/FakeJava.java @@ -0,0 +1 @@ +This is a fake java file \ No newline at end of file diff --git a/sootup.core/src/main/java/sootup/core/frontend/ClassProvider.java b/sootup.core/src/main/java/sootup/core/frontend/ClassProvider.java index 60f352d9be2..99a67c278f0 100644 --- a/sootup.core/src/main/java/sootup/core/frontend/ClassProvider.java +++ b/sootup.core/src/main/java/sootup/core/frontend/ClassProvider.java @@ -22,9 +22,9 @@ */ import java.nio.file.Path; +import java.util.Optional; import sootup.core.inputlocation.AnalysisInputLocation; import sootup.core.inputlocation.FileType; -import sootup.core.model.AbstractClass; import sootup.core.model.SootClass; import sootup.core.types.ClassType; @@ -34,9 +34,9 @@ * * @author Manuel Benz */ -public interface ClassProvider>> { +public interface ClassProvider>> { - AbstractClassSource createClassSource( + Optional> createClassSource( AnalysisInputLocation> inputLocation, Path sourcePath, ClassType classSignature); diff --git a/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmJavaClassProvider.java b/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmJavaClassProvider.java index b026a595382..e6bb38027a2 100644 --- a/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmJavaClassProvider.java +++ b/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmJavaClassProvider.java @@ -22,15 +22,16 @@ */ import java.io.IOException; import java.nio.file.Path; +import java.util.Optional; import javax.annotation.Nonnull; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.tree.ClassNode; -import sootup.core.frontend.AbstractClassSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import sootup.core.frontend.ClassProvider; -import sootup.core.frontend.ResolveException; +import sootup.core.frontend.SootClassSource; import sootup.core.inputlocation.AnalysisInputLocation; import sootup.core.inputlocation.FileType; -import sootup.core.jimple.basic.NoPositionInformation; import sootup.core.model.SootClass; import sootup.core.types.ClassType; import sootup.core.views.View; @@ -44,13 +45,14 @@ public class AsmJavaClassProvider implements ClassProvider { @Nonnull private final View view; + private static final @Nonnull Logger logger = LoggerFactory.getLogger(AsmJavaClassProvider.class); public AsmJavaClassProvider(@Nonnull View view) { this.view = view; } @Override - public AbstractClassSource createClassSource( + public Optional> createClassSource( AnalysisInputLocation> analysisInputLocation, Path sourcePath, ClassType classType) { @@ -58,23 +60,30 @@ public AbstractClassSource createClassSource( try { AsmUtil.initAsmClassSource(sourcePath, classNode); - } catch (IOException exception) { - throw new ResolveException( - exception.getMessage(), sourcePath, NoPositionInformation.getInstance(), exception); + } catch (IOException | IllegalArgumentException exception) { + logger.warn( + "ASM could not resolve class source of " + + classType + + " in " + + sourcePath + + " causing " + + exception.getMessage()); + return Optional.empty(); } JavaClassType klassType = (JavaClassType) classType; if (klassType instanceof ModuleJavaClassType && klassType.getClassName().equals(JavaModuleIdentifierFactory.MODULE_INFO_FILE)) { - throw new ResolveException( - "Can not create ClassSource from a module info descriptor!", sourcePath); + logger.warn("Can not create ClassSource from a module info descriptor! path:" + sourcePath); + return Optional.empty(); } else { if (klassType instanceof AnnotationType) { - return new AsmAnnotationClassSource( - analysisInputLocation, sourcePath, klassType, classNode); + return Optional.of( + new AsmAnnotationClassSource(analysisInputLocation, sourcePath, klassType, classNode)); } - return new AsmClassSource(analysisInputLocation, sourcePath, klassType, classNode); + return Optional.of( + new AsmClassSource(analysisInputLocation, sourcePath, klassType, classNode)); } } diff --git a/sootup.java.bytecode/src/main/java/sootup/java/bytecode/inputlocation/JrtFileSystemAnalysisInputLocation.java b/sootup.java.bytecode/src/main/java/sootup/java/bytecode/inputlocation/JrtFileSystemAnalysisInputLocation.java index 80df4e0d727..d3803134f6f 100644 --- a/sootup.java.bytecode/src/main/java/sootup/java/bytecode/inputlocation/JrtFileSystemAnalysisInputLocation.java +++ b/sootup.java.bytecode/src/main/java/sootup/java/bytecode/inputlocation/JrtFileSystemAnalysisInputLocation.java @@ -90,7 +90,7 @@ public Optional> getClassSource( "modules", modulePackageSignature.getModuleSignature().getModuleName()); Path foundClass = module.resolve(filepath); if (Files.isRegularFile(foundClass)) { - return Optional.of(classProvider.createClassSource(this, foundClass, klassType)); + return classProvider.createClassSource(this, foundClass, klassType); } else { return Optional.empty(); } @@ -104,7 +104,7 @@ public Optional> getClassSource( // check each module folder for the class Path foundfile = entry.resolve(filepath); if (Files.isRegularFile(foundfile)) { - return Optional.of(classProvider.createClassSource(this, foundfile, klassType)); + return classProvider.createClassSource(this, foundfile, klassType); } } } @@ -150,14 +150,13 @@ protected Stream> getClassSourcesInternal( .flatMap( p -> StreamUtils.optionalToStream( - Optional.of( - classProvider.createClassSource( - this, - p, - this.fromPath( - p.subpath(2, p.getNameCount()), - p.subpath(1, 2), - identifierFactory))))); + classProvider.createClassSource( + this, + p, + this.fromPath( + p.subpath(2, p.getNameCount()), + p.subpath(1, 2), + identifierFactory)))); } catch (IOException e) { throw new ResolveException("Error loading module " + moduleSignature, archiveRoot, e); } diff --git a/sootup.java.bytecode/src/main/java/sootup/java/bytecode/inputlocation/PathBasedAnalysisInputLocation.java b/sootup.java.bytecode/src/main/java/sootup/java/bytecode/inputlocation/PathBasedAnalysisInputLocation.java index 262fe3cbbbc..9ba65dda6f7 100644 --- a/sootup.java.bytecode/src/main/java/sootup/java/bytecode/inputlocation/PathBasedAnalysisInputLocation.java +++ b/sootup.java.bytecode/src/main/java/sootup/java/bytecode/inputlocation/PathBasedAnalysisInputLocation.java @@ -157,8 +157,7 @@ Collection> walkDirectory( .flatMap( p -> StreamUtils.optionalToStream( - Optional.of( - classProvider.createClassSource(this, p, factory.fromPath(dirPath, p))))) + classProvider.createClassSource(this, p, factory.fromPath(dirPath, p)))) .collect(Collectors.toList()); } catch (IOException e) { @@ -183,7 +182,7 @@ protected Optional> getClassSourceI return Optional.empty(); } - return Optional.of(classProvider.createClassSource(this, pathToClass, signature)); + return classProvider.createClassSource(this, pathToClass, signature); } private static class DirectoryBasedAnalysisInputLocation extends PathBasedAnalysisInputLocation { diff --git a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/AnalysisInputLocationTest.java b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/AnalysisInputLocationTest.java index dab4fe1236c..bc1f9b0ae1e 100644 --- a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/AnalysisInputLocationTest.java +++ b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/AnalysisInputLocationTest.java @@ -5,6 +5,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collection; +import java.util.List; import java.util.Optional; import sootup.core.IdentifierFactory; import sootup.core.frontend.AbstractClassSource; @@ -55,17 +56,18 @@ protected IdentifierFactory getIdentifierFactory() { } protected void testClassReceival( - AnalysisInputLocation ns, ClassType sig, int classesFound) { + AnalysisInputLocation ns, List sigs, int classesFound) { final JavaProject project = JavaProject.builder(new JavaLanguage(8)).addInputLocation(ns).build(); final JavaView view = project.createView(); - final Optional> clazzOpt = - ns.getClassSource(sig, view); - assertTrue(clazzOpt.isPresent()); - assertEquals(sig, clazzOpt.get().getClassType()); - + for (ClassType classType:sigs) { + final Optional> clazzOpt = + ns.getClassSource(classType, view); + assertTrue(clazzOpt.isPresent()); + assertEquals(classType, clazzOpt.get().getClassType()); + } final Collection> classSources = ns.getClassSources(view); assertEquals(classSources.size(), classesFound); diff --git a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/PathBasedAnalysisInputLocationTest.java b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/PathBasedAnalysisInputLocationTest.java index 273bd2be66e..33f4c877747 100644 --- a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/PathBasedAnalysisInputLocationTest.java +++ b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/PathBasedAnalysisInputLocationTest.java @@ -29,6 +29,7 @@ import categories.Java8Test; import java.io.File; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.EnumSet; @@ -273,7 +274,7 @@ public void testApk() { PathBasedAnalysisInputLocation.create(apk, null); final ClassType mainClass = getIdentifierFactory().getClassType("de.upb.futuresoot.fields.MainActivity"); - testClassReceival(pathBasedNamespace, mainClass, 1392); + testClassReceival(pathBasedNamespace, Collections.singletonList(mainClass), 1392); } @Test @@ -281,10 +282,10 @@ public void testJar() { PathBasedAnalysisInputLocation pathBasedNamespace = PathBasedAnalysisInputLocation.create(jar, null); - final ClassType class1 = getIdentifierFactory().getClassType("Employee", "ds"); - final ClassType mainClass = getIdentifierFactory().getClassType("MiniApp"); - testClassReceival(pathBasedNamespace, class1, 6); - testClassReceival(pathBasedNamespace, mainClass, 6); + ArrayList sigs=new ArrayList<>(); + sigs.add(getIdentifierFactory().getClassType("Employee", "ds")); + sigs.add(getIdentifierFactory().getClassType("MiniApp")); + testClassReceival(pathBasedNamespace, sigs, 6); } @Test @@ -292,7 +293,7 @@ public void testWar() { PathBasedAnalysisInputLocation pathBasedNamespace = PathBasedAnalysisInputLocation.create(war, null); final ClassType warClass1 = getIdentifierFactory().getClassType("SimpleWarRead"); - testClassReceival(pathBasedNamespace, warClass1, 19); + testClassReceival(pathBasedNamespace, Collections.singletonList(warClass1), 19); } @Test diff --git a/sootup.java.sourcecode/src/main/java/sootup/java/sourcecode/frontend/WalaJavaClassProvider.java b/sootup.java.sourcecode/src/main/java/sootup/java/sourcecode/frontend/WalaJavaClassProvider.java index 7f43e7a72a9..e241bb39334 100644 --- a/sootup.java.sourcecode/src/main/java/sootup/java/sourcecode/frontend/WalaJavaClassProvider.java +++ b/sootup.java.sourcecode/src/main/java/sootup/java/sourcecode/frontend/WalaJavaClassProvider.java @@ -347,9 +347,9 @@ private void setExclusions(@Nullable String exclusionFilePath) { } @Override - public SootClassSource createClassSource( + public Optional> createClassSource( AnalysisInputLocation> srcNamespace, Path sourcePath, ClassType type) { - return getClassSource(type).orElse(null); + return getClassSource(type); } @Override diff --git a/sootup.java.sourcecode/src/main/java/sootup/java/sourcecode/inputlocation/JavaSourcePathAnalysisInputLocation.java b/sootup.java.sourcecode/src/main/java/sootup/java/sourcecode/inputlocation/JavaSourcePathAnalysisInputLocation.java index 4876bed564c..7fd91ca9cfd 100644 --- a/sootup.java.sourcecode/src/main/java/sootup/java/sourcecode/inputlocation/JavaSourcePathAnalysisInputLocation.java +++ b/sootup.java.sourcecode/src/main/java/sootup/java/sourcecode/inputlocation/JavaSourcePathAnalysisInputLocation.java @@ -159,7 +159,7 @@ public Optional> getClassSource( @Nonnull ClassType type, @Nonnull View view) { for (String path : sourcePaths) { try { - return Optional.ofNullable(classProvider.createClassSource(this, Paths.get(path), type)); + return classProvider.createClassSource(this, Paths.get(path), type); } catch (ResolveException e) { log.debug(type + " not found in sourcePath " + path, e); } diff --git a/sootup.java.sourcecode/src/test/java/sootup/java/sourcecode/frontend/WalaJavaClassProviderTest.java b/sootup.java.sourcecode/src/test/java/sootup/java/sourcecode/frontend/WalaJavaClassProviderTest.java index ae1887fb03f..ca29d2cc1b8 100644 --- a/sootup.java.sourcecode/src/test/java/sootup/java/sourcecode/frontend/WalaJavaClassProviderTest.java +++ b/sootup.java.sourcecode/src/test/java/sootup/java/sourcecode/frontend/WalaJavaClassProviderTest.java @@ -1,15 +1,19 @@ package sootup.java.sourcecode.frontend; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import categories.Java8Test; import java.nio.file.Paths; +import java.util.Optional; import org.junit.Test; import org.junit.experimental.categories.Category; import sootup.core.frontend.SootClassSource; import sootup.core.signatures.PackageName; import sootup.core.util.ImmutableUtils; +import sootup.java.core.JavaSootClass; import sootup.java.core.types.JavaClassType; import sootup.java.sourcecode.inputlocation.JavaSourcePathAnalysisInputLocation; @@ -26,10 +30,18 @@ public void testCreateClassSource() { new JavaSourcePathAnalysisInputLocation( ImmutableUtils.immutableSet(srcDir), exclusionFilePath); JavaClassType type = new JavaClassType("Array1", PackageName.DEFAULT_PACKAGE); + JavaClassType faketype = new JavaClassType("FakeJava", PackageName.DEFAULT_PACKAGE); WalaJavaClassProvider provider = new WalaJavaClassProvider(srcDir, exclusionFilePath); - SootClassSource classSource = + + Optional> opFakeClass = + provider.createClassSource(inputLocation, Paths.get(srcDir), faketype); + assertFalse(opFakeClass.isPresent()); + + Optional> opClass = provider.createClassSource(inputLocation, Paths.get(srcDir), type); + assertTrue(opClass.isPresent()); + SootClassSource classSource = opClass.get(); assertEquals(type, classSource.getClassType()); diff --git a/sootup.jimple.parser/src/main/java/sootup/jimple/parser/JimpleAnalysisInputLocation.java b/sootup.jimple.parser/src/main/java/sootup/jimple/parser/JimpleAnalysisInputLocation.java index cc961cb0ea4..6b4c77f9e5b 100644 --- a/sootup.jimple.parser/src/main/java/sootup/jimple/parser/JimpleAnalysisInputLocation.java +++ b/sootup.jimple.parser/src/main/java/sootup/jimple/parser/JimpleAnalysisInputLocation.java @@ -85,8 +85,7 @@ List>> walkDirectory( .flatMap( p -> StreamUtils.optionalToStream( - Optional.of( - classProvider.createClassSource(this, p, factory.fromPath(dirPath, p))))) + classProvider.createClassSource(this, p, factory.fromPath(dirPath, p)))) .collect(Collectors.toList()); } catch (IOException e) { @@ -126,7 +125,7 @@ public Optional> getClassSource( } } - return Optional.of(classProvider.createClassSource(this, pathToClass, type)); + return classProvider.createClassSource(this, pathToClass, type); } @Override diff --git a/sootup.jimple.parser/src/main/java/sootup/jimple/parser/JimpleClassProvider.java b/sootup.jimple.parser/src/main/java/sootup/jimple/parser/JimpleClassProvider.java index 1f50f58fc94..ea0ffa2c960 100644 --- a/sootup.jimple.parser/src/main/java/sootup/jimple/parser/JimpleClassProvider.java +++ b/sootup.jimple.parser/src/main/java/sootup/jimple/parser/JimpleClassProvider.java @@ -3,9 +3,13 @@ import java.io.IOException; import java.nio.file.Path; import java.util.List; +import java.util.Optional; import javax.annotation.Nonnull; import org.antlr.v4.runtime.CharStreams; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import sootup.core.frontend.ClassProvider; +import sootup.core.frontend.ResolveException; import sootup.core.frontend.SootClassSource; import sootup.core.inputlocation.AnalysisInputLocation; import sootup.core.inputlocation.FileType; @@ -19,22 +23,32 @@ public class JimpleClassProvider bodyInterceptors; + private static final @Nonnull Logger logger = LoggerFactory.getLogger(JimpleClassProvider.class); + public JimpleClassProvider(List bodyInterceptors) { this.bodyInterceptors = bodyInterceptors; } @Override - public SootClassSource createClassSource( + public Optional> createClassSource( AnalysisInputLocation> inputlocation, Path sourcePath, ClassType classSignature) { try { final JimpleConverter jimpleConverter = new JimpleConverter(); - return jimpleConverter.run( - CharStreams.fromPath(sourcePath), inputlocation, sourcePath, bodyInterceptors); - } catch (IOException e) { - throw new RuntimeException(e); + return Optional.of( + jimpleConverter.run( + CharStreams.fromPath(sourcePath), inputlocation, sourcePath, bodyInterceptors)); + } catch (IOException | ResolveException e) { + logger.warn( + "The jimple file of " + + classSignature + + " in path: " + + sourcePath + + " could not be converted because of: " + + e.getMessage()); + return Optional.empty(); } } diff --git a/sootup.jimple.parser/src/test/java/resources/jimple/FakeJimple.jimple b/sootup.jimple.parser/src/test/java/resources/jimple/FakeJimple.jimple new file mode 100644 index 00000000000..e320f3f2c48 --- /dev/null +++ b/sootup.jimple.parser/src/test/java/resources/jimple/FakeJimple.jimple @@ -0,0 +1 @@ +This is not a correct jimple file \ No newline at end of file diff --git a/sootup.jimple.parser/src/test/java/sootup/jimple/parser/JimpleAnalysisInputLocationTest.java b/sootup.jimple.parser/src/test/java/sootup/jimple/parser/JimpleAnalysisInputLocationTest.java index a05bc8bd7ad..ce86f569cb0 100644 --- a/sootup.jimple.parser/src/test/java/sootup/jimple/parser/JimpleAnalysisInputLocationTest.java +++ b/sootup.jimple.parser/src/test/java/sootup/jimple/parser/JimpleAnalysisInputLocationTest.java @@ -69,6 +69,29 @@ public PackageName getPackageName() { } }; + final ClassType classTypeFake = + new ClassType() { + @Override + public boolean isBuiltInClass() { + return false; + } + + @Override + public String getFullyQualifiedName() { + return "jimple.FakeJimple"; + } + + @Override + public String getClassName() { + return "FakeJimple"; + } + + @Override + public PackageName getPackageName() { + return new PackageName("jimple"); + } + }; + final String resourceDir = "src/test/java/resources/"; // files direct in dir @@ -79,6 +102,8 @@ public PackageName getPackageName() { assertTrue(classSource1.isPresent()); final Optional> classSource2 = jv1.getClass(classType); assertFalse(classSource2.isPresent()); + final Optional> classSourceNon = jv1.getClass(classTypeFake); + assertFalse(classSourceNon.isPresent()); // files in subdir structure final JimpleAnalysisInputLocation inputLocation2 = From aab87242fa1cee1b2a8776d6c0a79e246a5c602a Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 18 Aug 2023 14:18:30 +0200 Subject: [PATCH 17/36] fmt --- .../java/bytecode/inputlocation/AnalysisInputLocationTest.java | 2 +- .../inputlocation/PathBasedAnalysisInputLocationTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/AnalysisInputLocationTest.java b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/AnalysisInputLocationTest.java index bc1f9b0ae1e..c740571158b 100644 --- a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/AnalysisInputLocationTest.java +++ b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/AnalysisInputLocationTest.java @@ -62,7 +62,7 @@ protected void testClassReceival( JavaProject.builder(new JavaLanguage(8)).addInputLocation(ns).build(); final JavaView view = project.createView(); - for (ClassType classType:sigs) { + for (ClassType classType : sigs) { final Optional> clazzOpt = ns.getClassSource(classType, view); assertTrue(clazzOpt.isPresent()); diff --git a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/PathBasedAnalysisInputLocationTest.java b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/PathBasedAnalysisInputLocationTest.java index 33f4c877747..b60892e6002 100644 --- a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/PathBasedAnalysisInputLocationTest.java +++ b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/inputlocation/PathBasedAnalysisInputLocationTest.java @@ -282,7 +282,7 @@ public void testJar() { PathBasedAnalysisInputLocation pathBasedNamespace = PathBasedAnalysisInputLocation.create(jar, null); - ArrayList sigs=new ArrayList<>(); + ArrayList sigs = new ArrayList<>(); sigs.add(getIdentifierFactory().getClassType("Employee", "ds")); sigs.add(getIdentifierFactory().getClassType("MiniApp")); testClassReceival(pathBasedNamespace, sigs, 6); From 95496b3cb45ebb58dd31b6157d45093243667fd8 Mon Sep 17 00:00:00 2001 From: stschott Date: Fri, 1 Sep 2023 12:24:06 +0200 Subject: [PATCH 18/36] update doc --- docs/getting-started.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/getting-started.md b/docs/getting-started.md index 4e5d609bb81..d2b41ac9e60 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -53,6 +53,10 @@ You can use bytecode analysis typically when you do not have access to the sourc If you have access to the source code, it is also possible to create a project for analyzing source code. Following example shows how to create project for analyzing Java source code. +!!! info "Experimental" + + The source code frontend is experimental and should only be used for testing purposes. You should compile the code for analysis first and use the bytecode frontend instead. + !!! example "Create a project to analyze Java source code" ~~~java From 51afb96c50832d874e575296b0d51a62924c3bb4 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 8 Sep 2023 10:45:13 +0200 Subject: [PATCH 19/36] remove incomplete multi release handling in the class type generation via a given path --- .../java/core/JavaIdentifierFactory.java | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/sootup.java.core/src/main/java/sootup/java/core/JavaIdentifierFactory.java b/sootup.java.core/src/main/java/sootup/java/core/JavaIdentifierFactory.java index c9742affc49..963179dfd0d 100644 --- a/sootup.java.core/src/main/java/sootup/java/core/JavaIdentifierFactory.java +++ b/sootup.java.core/src/main/java/sootup/java/core/JavaIdentifierFactory.java @@ -33,7 +33,6 @@ import javax.annotation.Nonnull; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.ClassUtils; -import org.apache.commons.lang3.StringUtils; import sootup.core.IdentifierFactory; import sootup.core.model.SootClass; import sootup.core.signatures.FieldSignature; @@ -234,24 +233,15 @@ public AnnotationType getAnnotationType(final String fullyQualifiedClassName) { @Override @Nonnull public JavaClassType fromPath(@Nonnull final Path rootDirectory, @Nonnull final Path file) { - String path = file.toString(); - String separator = file.getFileSystem().getSeparator(); - - // for multi release jars, remove beginning of path - // /META-INF/versions/15/de/upb... - // we only want /de/upb... - if (path.startsWith("/META-INF/")) { - // start at 4th separator - int index = StringUtils.ordinalIndexOf(path, separator, 4); - path = path.substring(index); - } final int nameCountBaseDir = rootDirectory.toString().isEmpty() ? 0 : rootDirectory.getNameCount(); String fullyQualifiedName = FilenameUtils.removeExtension( - file.subpath(nameCountBaseDir, file.getNameCount()).toString().replace(separator, ".")); + file.subpath(nameCountBaseDir, file.getNameCount()) + .toString() + .replace(file.getFileSystem().getSeparator(), ".")); return getClassType(fullyQualifiedName); } @@ -524,7 +514,7 @@ public MethodSubSignature parseMethodSubSignature(@Nonnull String subSignature) return true; }) - .map(typeName -> getType(typeName)) + .map(this::getType) .collect(Collectors.toList()); return getMethodSubSignature(methodName, getType(returnName), argsList); From 1ec5b1256639b21b4f6249de2918694386723f03 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 8 Sep 2023 10:57:35 +0200 Subject: [PATCH 20/36] adapted incompleteSuperclassesOf to the new thrown exception in the class resolving method --- .../src/main/java/sootup/core/typehierarchy/TypeHierarchy.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sootup.core/src/main/java/sootup/core/typehierarchy/TypeHierarchy.java b/sootup.core/src/main/java/sootup/core/typehierarchy/TypeHierarchy.java index 6e70a97ae20..5efed1cff0c 100644 --- a/sootup.core/src/main/java/sootup/core/typehierarchy/TypeHierarchy.java +++ b/sootup.core/src/main/java/sootup/core/typehierarchy/TypeHierarchy.java @@ -28,7 +28,6 @@ import javax.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import sootup.core.frontend.ResolveException; import sootup.core.types.*; import sootup.core.views.View; @@ -198,7 +197,7 @@ default List incompleteSuperClassesOf(@Nonnull ClassType classType) { superClasses.add(currentSuperClass); currentSuperClass = superClassOf(currentSuperClass); } - } catch (ResolveException ex) { + } catch (IllegalArgumentException ex) { logger.warn( "Could not find " + (currentSuperClass != null ? currentSuperClass : classType) From 32f856e4189f79471d1f6b7daa449b0a0f423d3a Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 8 Sep 2023 11:39:38 +0200 Subject: [PATCH 21/36] added test case for incomplete Superclasses --- .../IncompleteSuperclassTest.java | 31 +++++++++++++++++++ .../IncompleteSuperclass/SubClassA.java | 3 ++ .../IncompleteSuperclass/SubClassB.java | 3 ++ 3 files changed, 37 insertions(+) create mode 100644 sootup.tests/src/test/java/sootup/tests/typehierarchy/viewtypehierarchytestcase/IncompleteSuperclassTest.java create mode 100644 sootup.tests/src/test/resources/javatypehierarchy/IncompleteSuperclass/SubClassA.java create mode 100644 sootup.tests/src/test/resources/javatypehierarchy/IncompleteSuperclass/SubClassB.java diff --git a/sootup.tests/src/test/java/sootup/tests/typehierarchy/viewtypehierarchytestcase/IncompleteSuperclassTest.java b/sootup.tests/src/test/java/sootup/tests/typehierarchy/viewtypehierarchytestcase/IncompleteSuperclassTest.java new file mode 100644 index 00000000000..c51a52b0a8f --- /dev/null +++ b/sootup.tests/src/test/java/sootup/tests/typehierarchy/viewtypehierarchytestcase/IncompleteSuperclassTest.java @@ -0,0 +1,31 @@ +package sootup.tests.typehierarchy.viewtypehierarchytestcase; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static sootup.core.util.ImmutableUtils.immutableList; + +import categories.Java8Test; +import com.google.common.collect.ImmutableList; +import java.util.List; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import sootup.core.typehierarchy.ViewTypeHierarchy; +import sootup.core.types.ClassType; +import sootup.tests.typehierarchy.JavaTypeHierarchyTestBase; + +/** @author Jonas Klauke * */ +@Category(Java8Test.class) +public class IncompleteSuperclassTest extends JavaTypeHierarchyTestBase { + @Test + public void method() { + ViewTypeHierarchy typeHierarchy = + (ViewTypeHierarchy) customTestWatcher.getView().getTypeHierarchy(); + List superclasses = + typeHierarchy.incompleteSuperClassesOf(getClassType("SubClassB")); + ClassType object = getClassType("java.lang.Object"); + ImmutableList expectedSuperClasses = + immutableList(getClassType("SubClassA"), object); + assertEquals(expectedSuperClasses, superclasses); + assertFalse(customTestWatcher.getView().getClass(object).isPresent()); + } +} diff --git a/sootup.tests/src/test/resources/javatypehierarchy/IncompleteSuperclass/SubClassA.java b/sootup.tests/src/test/resources/javatypehierarchy/IncompleteSuperclass/SubClassA.java new file mode 100644 index 00000000000..b3301dd276e --- /dev/null +++ b/sootup.tests/src/test/resources/javatypehierarchy/IncompleteSuperclass/SubClassA.java @@ -0,0 +1,3 @@ +public class SubClassA { + +} \ No newline at end of file diff --git a/sootup.tests/src/test/resources/javatypehierarchy/IncompleteSuperclass/SubClassB.java b/sootup.tests/src/test/resources/javatypehierarchy/IncompleteSuperclass/SubClassB.java new file mode 100644 index 00000000000..d278f9127fc --- /dev/null +++ b/sootup.tests/src/test/resources/javatypehierarchy/IncompleteSuperclass/SubClassB.java @@ -0,0 +1,3 @@ +public class SubClassB extends SubClassA { + +} \ No newline at end of file From f2e01b2091d5a00dbbc0a4d6c9b20accce6e6b5d Mon Sep 17 00:00:00 2001 From: Stefan Schott <64211065+stschott@users.noreply.github.com> Date: Thu, 14 Sep 2023 14:28:07 +0200 Subject: [PATCH 22/36] add javadoc link to readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9ba2e4492ff..051d37be1da 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@

-# SootUp library ![Java CI with Maven](https://github.com/soot-oss/SootUp/workflows/Java%20CI%20with%20Maven/badge.svg?branch=develop) [![codecov](https://codecov.io/gh/soot-oss/SootUp/branch/develop/graph/badge.svg?token=ELA7U7IAWD)](https://codecov.io/gh/soot-oss/SootUp) +# SootUp library ![Java CI with Maven](https://github.com/soot-oss/SootUp/workflows/Java%20CI%20with%20Maven/badge.svg?branch=develop) [![codecov](https://codecov.io/gh/soot-oss/SootUp/branch/develop/graph/badge.svg?token=ELA7U7IAWD)](https://codecov.io/gh/soot-oss/SootUp) [![javadoc](https://javadoc.io/badge2/org.soot-oss/sootup.core/javadoc.svg)](https://javadoc.io/doc/org.soot-oss/sootup.core) This is the home of the **SootUp** project. A complete overhaul of the good, old static analysis framework [Soot](https://github.com/soot-oss/soot). From 7047cdfa09c0031d379ecf3a55ceccd5dca065a6 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 15 Sep 2023 18:45:36 +0200 Subject: [PATCH 23/36] fixed that nrArgs can be -1 if the while condition is false but the -- instruction is still performed --- .../java/sootup/java/bytecode/frontend/AsmMethodSource.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java b/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java index 5b43a1771a1..a7ba0680728 100644 --- a/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java +++ b/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java @@ -1394,7 +1394,8 @@ private void convertInvokeDynamicInsn(@Nonnull InvokeDynamicInsnNode insn) { oprs = new Operand[nrArgs + 1]; } if (oprs != null) { - while (nrArgs-- > 0) { + while (nrArgs > 0) { + nrArgs--; oprs[nrArgs] = operandStack.pop(types.get(nrArgs)); } if (!isStaticInvokeExpr) { From 725710f19c09bf1cf3373207dd349be2bcdc5039 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Tue, 19 Sep 2023 13:01:47 +0200 Subject: [PATCH 24/36] improved the getting started documentation --- docs/getting-started.md | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/docs/getting-started.md b/docs/getting-started.md index d2b41ac9e60..ece9f35b4d7 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -40,10 +40,8 @@ You can use bytecode analysis typically when you do not have access to the sourc !!! example "Create a project to analyze Java bytecode" ~~~java - Path pathToBinary = Paths.get("src/test/resources/BasicSetup/binary"); - AnalysisInputLocation inputLocation = - PathBasedAnalysisInputLocation.createForClassContainer(pathToBinary); + new JavaClassPathAnalysisInputLocation("path2Binary"); JavaLanguage language = new JavaLanguage(8); @@ -60,10 +58,8 @@ If you have access to the source code, it is also possible to create a project f !!! example "Create a project to analyze Java source code" ~~~java - Path pathToSource = Paths.get("src/test/resources/BasicSetup/source"); - AnalysisInputLocation inputLocation = - new JavaSourcePathAnalysisInputLocation(pathToSource.toString()); + new JavaSourcePathAnalysisInputLocation("path2Source"); JavaLanguage language = new JavaLanguage(8); @@ -76,7 +72,7 @@ If you have a [Jimple](../jimple) file, you can create a project for analyzing j !!! example "Create a project to analyze jimple code" ~~~java - Path pathToJimple = Paths.get("src/test/resources/BasicSetup/jimple"); + Path pathToJimple = Paths.get("path2Jimple"); AnalysisInputLocation inputLocation = new JimpleAnalysisInputLocation(pathToJimple); @@ -124,10 +120,13 @@ Let's say the following is the target program that we want to analyze: } - public static void main(String[] var0) { - - System.out.println("Hello World!"); - + public static void main(String[] args) { + HelloWorld hw = new HelloWorld; + hw.hello(); + } + + public void hello() { + } } @@ -213,9 +212,8 @@ Below we show a comparison of the code so far with the same functionality in soo === "SootUp" ``` java - Path pathToBinary = Paths.get("src/test/resources/BasicSetup/binary"); AnalysisInputLocation inputLocation = - PathBasedAnalysisInputLocation.createForClassContainer(pathToBinary); + new JavaClassPathAnalysisInputLocation("path2Binary"); JavaLanguage language = new JavaLanguage(8); From 9343413bb5121d57f4ea03cda209e3ad0e20b81a Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Tue, 19 Sep 2023 13:05:20 +0200 Subject: [PATCH 25/36] fixed example --- docs/getting-started.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started.md b/docs/getting-started.md index ece9f35b4d7..d913d88bd55 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -121,7 +121,7 @@ Let's say the following is the target program that we want to analyze: } public static void main(String[] args) { - HelloWorld hw = new HelloWorld; + HelloWorld hw = new HelloWorld(); hw.hello(); } From e5086703a4f8b6244cf001e8885f1cc435f3a500 Mon Sep 17 00:00:00 2001 From: liyiwei <979621500@qq.com> Date: Mon, 9 Oct 2023 21:36:02 +0800 Subject: [PATCH 26/36] format --- .../core/typehierarchy/MethodDispatchResolver.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java b/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java index 16c604ceb09..80cd7734ac9 100644 --- a/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java +++ b/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java @@ -22,12 +22,6 @@ */ import com.google.common.collect.Sets; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; -import javax.annotation.Nonnull; import sootup.core.frontend.ResolveException; import sootup.core.jimple.common.expr.JSpecialInvokeExpr; import sootup.core.model.Method; @@ -37,6 +31,13 @@ import sootup.core.types.ClassType; import sootup.core.views.View; +import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + public final class MethodDispatchResolver { private MethodDispatchResolver() {} From e4e5d762e62d5b67e0bb3a22e66638c81a4960da Mon Sep 17 00:00:00 2001 From: liyiwei <979621500@qq.com> Date: Mon, 9 Oct 2023 21:41:13 +0800 Subject: [PATCH 27/36] inline findConcreteMethodInSootClass with sootClass.getMethod --- .../typehierarchy/MethodDispatchResolver.java | 31 +++---------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java b/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java index 80cd7734ac9..2b168fcef17 100644 --- a/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java +++ b/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java @@ -86,7 +86,7 @@ public static Set resolveAbstractDispatch( () -> new ResolveException( "Could not resolve " + subtype + ", but found it in hierarchy."))) - .map(sootClass -> findConcreteMethodInSootClass(sootClass, m)) + .map(sootClass -> sootClass.getMethod(m.getSubSignature())) .filter(Optional::isPresent) .map(Optional::get) .filter(method -> !method.isAbstract()) @@ -112,7 +112,7 @@ public static Set resolveAllDispatchesInClasses( new ResolveException( "Could not resolve " + subtype + ", but found it in hierarchy."))) .filter(c -> classes.contains(c.getType())) - .map(sootClass -> findConcreteMethodInSootClass(sootClass, m)) + .map(sootClass -> sootClass.getMethod(m.getSubSignature())) .filter(Optional::isPresent) .map(Optional::get) .filter(method -> !method.isAbstract()) @@ -198,7 +198,7 @@ public static Optional resolveConcreteDispatch( classesInHierachyOrder.add(superClass); - SootMethod concreteMethod = findConcreteMethodInSootClass(superClass, m).orElse(null); + SootMethod concreteMethod = superClass.getMethod(m.getSubSignature()).orElse(null); if (concreteMethod != null && !concreteMethod.isAbstract()) { // found method is not abstract return Optional.of(concreteMethod.getSignature()); @@ -234,7 +234,7 @@ public static Optional resolveConcreteDispatch( // add found default method to possibleDefaultMethods Optional concreteMethod = - findConcreteMethodInSootClass(currentInterface, m); + currentInterface.getMethod(m.getSubSignature()); concreteMethod.ifPresent(possibleDefaultMethods::add); // if no default message is found search the default message in super interfaces @@ -283,29 +283,6 @@ private static List> getSootClassesOfInterfaces( .collect(Collectors.toList()); } - /** - * finds the concrete method in a SootClass - * - *

this method returns the concrete method of given method signature in a SootClass. Due to - * covariant, the given method signature can differ from the concrete method at the return type - * The method goes through all methods of the given SootClass and searches for a method which can - * dispatch. - * - * @param sootClass The method is searched in this SootClass - * @param methodSignature the signature of the searched method - * @return an Optional Object that can contain the found concrete method in the given SootClass - */ - private static Optional findConcreteMethodInSootClass( - SootClass sootClass, MethodSignature methodSignature) { - return sootClass.getMethods().stream() - .filter( - potentialTarget -> - methodSignature - .getSubSignature() - .equals(potentialTarget.getSignature().getSubSignature())) - .findAny(); - } - /** * Resolves the actual method called by the specialInvokeExpr that is contained by * container. From 7ba783f2bb928d32801f37f43c56f6507b0b44cc Mon Sep 17 00:00:00 2001 From: liyiwei <979621500@qq.com> Date: Mon, 9 Oct 2023 21:41:52 +0800 Subject: [PATCH 28/36] typo cleanup --- .../sootup/core/typehierarchy/MethodDispatchResolver.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java b/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java index 2b168fcef17..e6bf587f51f 100644 --- a/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java +++ b/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java @@ -184,7 +184,7 @@ public static Optional resolveConcreteDispatch( TypeHierarchy hierarchy = view.getTypeHierarchy(); ClassType superClassType = m.getDeclClassType(); SootClass startClass = view.getClass(superClassType).orElse(null); - ArrayList> classesInHierachyOrder = new ArrayList<>(); + ArrayList> classesInHierarchyOrder = new ArrayList<>(); // search concrete method in the class itself and its super classes do { @@ -196,7 +196,7 @@ public static Optional resolveConcreteDispatch( new ResolveException( "Did not find class " + finalSuperClassType + " in View")); - classesInHierachyOrder.add(superClass); + classesInHierarchyOrder.add(superClass); SootMethod concreteMethod = superClass.getMethod(m.getSubSignature()).orElse(null); if (concreteMethod != null && !concreteMethod.isAbstract()) { @@ -209,7 +209,7 @@ public static Optional resolveConcreteDispatch( // A not implemented method of an abstract class results into an abstract method return Optional.empty(); } - // found method is abstract and the startclass is not abstract + // found method is abstract and the start class is not abstract throw new ResolveException( "Could not find concrete method for " + m + " because the method is abstract"); } @@ -220,7 +220,7 @@ public static Optional resolveConcreteDispatch( // No super class contains the implemented method, search the concrete method in interfaces // first collect all interfaces and super interfaces List> worklist = - classesInHierachyOrder.stream() + classesInHierarchyOrder.stream() .flatMap(sootClass -> getSootClassesOfInterfaces(view, sootClass).stream()) .collect(Collectors.toList()); ArrayList> processedInterface = new ArrayList<>(); From fc3bd0df7a175b5bb9e684c1892aabb82f96c571 Mon Sep 17 00:00:00 2001 From: liyiwei <979621500@qq.com> Date: Mon, 9 Oct 2023 22:37:48 +0800 Subject: [PATCH 29/36] refactor resolveConcreteDispatch --- .../typehierarchy/MethodDispatchResolver.java | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java b/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java index e6bf587f51f..56f17a25832 100644 --- a/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java +++ b/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java @@ -37,6 +37,7 @@ import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; public final class MethodDispatchResolver { private MethodDispatchResolver() {} @@ -173,6 +174,19 @@ public static boolean canDispatch( || hierarchy.isSubtype(called.getType(), potentialTarget.getType())); // covariant } + /** + * Returns all superclasses of classType(inclusive) up to java.lang.Object, which + * will be the last entry in the list, or till one of the superclasses is not contained in view. + */ + private static List> findSuperClassesInclusive( + View> view, ClassType classType) { + return Stream.concat( + Stream.of(classType), + view.getTypeHierarchy().incompleteSuperClassesOf(classType).stream() + ).flatMap(t -> view.getClass(t).map(Stream::of).orElseGet(Stream::empty)) + .collect(Collectors.toList()); + } + /** * Searches for the signature of the method that is the concrete implementation of m. * This is done by checking each superclass and the class itself for whether it contains the @@ -182,23 +196,12 @@ public static boolean canDispatch( public static Optional resolveConcreteDispatch( View> view, MethodSignature m) { TypeHierarchy hierarchy = view.getTypeHierarchy(); - ClassType superClassType = m.getDeclClassType(); - SootClass startClass = view.getClass(superClassType).orElse(null); - ArrayList> classesInHierarchyOrder = new ArrayList<>(); - - // search concrete method in the class itself and its super classes - do { - ClassType finalSuperClassType = superClassType; - SootClass superClass = - view.getClass(superClassType) - .orElseThrow( - () -> - new ResolveException( - "Did not find class " + finalSuperClassType + " in View")); + ClassType current = m.getDeclClassType(); + SootClass startClass = view.getClass(current).orElse(null); + List> classesInHierarchyOrder = findSuperClassesInclusive(view, current); - classesInHierarchyOrder.add(superClass); - - SootMethod concreteMethod = superClass.getMethod(m.getSubSignature()).orElse(null); + for (SootClass currentClass : classesInHierarchyOrder) { + SootMethod concreteMethod = currentClass.getMethod(m.getSubSignature()).orElse(null); if (concreteMethod != null && !concreteMethod.isAbstract()) { // found method is not abstract return Optional.of(concreteMethod.getSignature()); @@ -209,13 +212,12 @@ public static Optional resolveConcreteDispatch( // A not implemented method of an abstract class results into an abstract method return Optional.empty(); } - // found method is abstract and the start class is not abstract + // found method is abstract and the startClass is not abstract throw new ResolveException( "Could not find concrete method for " + m + " because the method is abstract"); } + } - superClassType = hierarchy.superClassOf(superClassType); - } while (superClassType != null); // No super class contains the implemented method, search the concrete method in interfaces // first collect all interfaces and super interfaces From 4705075c2a312e4c9262c16714bd3c5bd249b841 Mon Sep 17 00:00:00 2001 From: liyiwei <979621500@qq.com> Date: Mon, 9 Oct 2023 23:33:03 +0800 Subject: [PATCH 30/36] format --- .../typehierarchy/MethodDispatchResolver.java | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java b/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java index 56f17a25832..11f83a7e73e 100644 --- a/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java +++ b/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java @@ -22,6 +22,13 @@ */ import com.google.common.collect.Sets; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import javax.annotation.Nonnull; import sootup.core.frontend.ResolveException; import sootup.core.jimple.common.expr.JSpecialInvokeExpr; import sootup.core.model.Method; @@ -31,14 +38,6 @@ import sootup.core.types.ClassType; import sootup.core.views.View; -import javax.annotation.Nonnull; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - public final class MethodDispatchResolver { private MethodDispatchResolver() {} @@ -87,7 +86,7 @@ public static Set resolveAbstractDispatch( () -> new ResolveException( "Could not resolve " + subtype + ", but found it in hierarchy."))) - .map(sootClass -> sootClass.getMethod(m.getSubSignature())) + .map(sootClass -> sootClass.getMethod(m.getSubSignature())) .filter(Optional::isPresent) .map(Optional::get) .filter(method -> !method.isAbstract()) @@ -113,7 +112,7 @@ public static Set resolveAllDispatchesInClasses( new ResolveException( "Could not resolve " + subtype + ", but found it in hierarchy."))) .filter(c -> classes.contains(c.getType())) - .map(sootClass -> sootClass.getMethod(m.getSubSignature())) + .map(sootClass -> sootClass.getMethod(m.getSubSignature())) .filter(Optional::isPresent) .map(Optional::get) .filter(method -> !method.isAbstract()) @@ -175,16 +174,17 @@ public static boolean canDispatch( } /** - * Returns all superclasses of classType(inclusive) up to java.lang.Object, which - * will be the last entry in the list, or till one of the superclasses is not contained in view. + * Returns all superclasses of classType(inclusive) up to java.lang.Object + * , which will be the last entry in the list, or till one of the superclasses is not + * contained in view. */ private static List> findSuperClassesInclusive( - View> view, ClassType classType) { + View> view, ClassType classType) { return Stream.concat( - Stream.of(classType), - view.getTypeHierarchy().incompleteSuperClassesOf(classType).stream() - ).flatMap(t -> view.getClass(t).map(Stream::of).orElseGet(Stream::empty)) - .collect(Collectors.toList()); + Stream.of(classType), + view.getTypeHierarchy().incompleteSuperClassesOf(classType).stream()) + .flatMap(t -> view.getClass(t).map(Stream::of).orElseGet(Stream::empty)) + .collect(Collectors.toList()); } /** @@ -218,11 +218,10 @@ public static Optional resolveConcreteDispatch( } } - // No super class contains the implemented method, search the concrete method in interfaces // first collect all interfaces and super interfaces List> worklist = - classesInHierarchyOrder.stream() + classesInHierarchyOrder.stream() .flatMap(sootClass -> getSootClassesOfInterfaces(view, sootClass).stream()) .collect(Collectors.toList()); ArrayList> processedInterface = new ArrayList<>(); @@ -236,7 +235,7 @@ public static Optional resolveConcreteDispatch( // add found default method to possibleDefaultMethods Optional concreteMethod = - currentInterface.getMethod(m.getSubSignature()); + currentInterface.getMethod(m.getSubSignature()); concreteMethod.ifPresent(possibleDefaultMethods::add); // if no default message is found search the default message in super interfaces From 312465ce31605328f3cadc5271107ac40f256742 Mon Sep 17 00:00:00 2001 From: liyiwei <979621500@qq.com> Date: Tue, 10 Oct 2023 22:47:38 +0800 Subject: [PATCH 31/36] unify conditions --- .../typehierarchy/MethodDispatchResolver.java | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java b/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java index 11f83a7e73e..ff6f94fb36d 100644 --- a/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java +++ b/sootup.core/src/main/java/sootup/core/typehierarchy/MethodDispatchResolver.java @@ -201,20 +201,21 @@ public static Optional resolveConcreteDispatch( List> classesInHierarchyOrder = findSuperClassesInclusive(view, current); for (SootClass currentClass : classesInHierarchyOrder) { - SootMethod concreteMethod = currentClass.getMethod(m.getSubSignature()).orElse(null); - if (concreteMethod != null && !concreteMethod.isAbstract()) { - // found method is not abstract - return Optional.of(concreteMethod.getSignature()); - } - if (concreteMethod != null && concreteMethod.isAbstract()) { - if (startClass.isAbstract() - && !startClass.getType().equals(concreteMethod.getDeclaringClassType())) { - // A not implemented method of an abstract class results into an abstract method - return Optional.empty(); + SootMethod method = currentClass.getMethod(m.getSubSignature()).orElse(null); + if (method != null) { + if (!method.isAbstract()) { + // found method is not abstract + return Optional.of(method.getSignature()); + } else { + if (startClass.isAbstract() + && !startClass.getType().equals(method.getDeclaringClassType())) { + // A not implemented method of an abstract class results into an abstract method + return Optional.empty(); + } + // found method is abstract and the startClass is not abstract + throw new ResolveException( + "Could not find concrete method for " + m + " because the method is abstract"); } - // found method is abstract and the startClass is not abstract - throw new ResolveException( - "Could not find concrete method for " + m + " because the method is abstract"); } } From ee41bafa92304eb345dc52bb17ae410cd4d40dd4 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Mon, 16 Oct 2023 18:31:07 +0200 Subject: [PATCH 32/36] removed static invoke handling caused by wrongly adaption of soot code for SootUp. SootUp does not model lambda expressions as static method calls. --- .../java/bytecode/frontend/AsmMethodSource.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java b/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java index a7ba0680728..857b4d21349 100644 --- a/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java +++ b/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java @@ -73,7 +73,6 @@ import sootup.core.jimple.common.expr.JInstanceOfExpr; import sootup.core.jimple.common.expr.JNewArrayExpr; import sootup.core.jimple.common.expr.JNewMultiArrayExpr; -import sootup.core.jimple.common.expr.JStaticInvokeExpr; import sootup.core.jimple.common.ref.*; import sootup.core.jimple.common.stmt.*; import sootup.core.jimple.javabytecode.stmt.JSwitchStmt; @@ -1387,20 +1386,12 @@ private void convertInvokeDynamicInsn(@Nonnull InvokeDynamicInsnNode insn) { List types = expr.getMethodSignature().getParameterTypes(); Operand[] oprs; int nrArgs = types.size(); - final boolean isStaticInvokeExpr = expr instanceof JStaticInvokeExpr; - if (isStaticInvokeExpr) { - oprs = (nrArgs == 0) ? null : new Operand[nrArgs]; - } else { - oprs = new Operand[nrArgs + 1]; - } + oprs = (nrArgs == 0) ? null : new Operand[nrArgs]; if (oprs != null) { while (nrArgs > 0) { nrArgs--; oprs[nrArgs] = operandStack.pop(types.get(nrArgs)); } - if (!isStaticInvokeExpr) { - oprs[oprs.length - 1] = operandStack.pop(); - } frame.mergeIn(currentLineNumber, oprs); } returnType = expr.getType(); From 74da0deb0dc141068fe0bd838d025b66d97bd43c Mon Sep 17 00:00:00 2001 From: liyiwei <979621500@qq.com> Date: Tue, 17 Oct 2023 00:34:56 +0800 Subject: [PATCH 33/36] clean up assertions --- .../java/sootup/callgraph/AbstractCallGraphAlgorithm.java | 8 +++++--- .../java/sootup/core/typehierarchy/TypeHierarchy.java | 2 +- .../src/main/java/sootup/java/core/views/JavaView.java | 6 +----- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java b/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java index eb899f1e0af..0cb5d0c7275 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java @@ -291,7 +291,7 @@ protected final T findMethodInHierarchy( if (optSc.isPresent()) { SootClass sc = optSc.get(); - List superClasses = view.getTypeHierarchy().superClassesOf(sc.getType()); + List superClasses = view.getTypeHierarchy().incompleteSuperClassesOf(sc.getType()); Set interfaces = view.getTypeHierarchy().implementedInterfacesOf(sc.getType()); superClasses.addAll(interfaces); @@ -364,7 +364,7 @@ public CallGraph addClass(@Nonnull CallGraph oldCallGraph, @Nonnull JavaClassTyp processWorkList(view, workList, processed, updated); // Step 2: Add edges from old methods to methods overridden in the new class - List superClasses = view.getTypeHierarchy().superClassesOf(classType); + List superClasses = view.getTypeHierarchy().incompleteSuperClassesOf(classType); Set implementedInterfaces = view.getTypeHierarchy().implementedInterfacesOf(classType); Stream superTypes = @@ -376,7 +376,9 @@ public CallGraph addClass(@Nonnull CallGraph oldCallGraph, @Nonnull JavaClassTyp .collect(Collectors.toSet()); superTypes - .map(view::getClassOrThrow) + .map(view::getClass) + .filter(Optional::isPresent) + .map(Optional::get) .flatMap(superType -> superType.getMethods().stream()) .map(Method::getSignature) .filter( diff --git a/sootup.core/src/main/java/sootup/core/typehierarchy/TypeHierarchy.java b/sootup.core/src/main/java/sootup/core/typehierarchy/TypeHierarchy.java index 5efed1cff0c..5a5b0e1ab59 100644 --- a/sootup.core/src/main/java/sootup/core/typehierarchy/TypeHierarchy.java +++ b/sootup.core/src/main/java/sootup/core/typehierarchy/TypeHierarchy.java @@ -154,7 +154,7 @@ default boolean isSubtype(@Nonnull Type supertype, @Nonnull Type potentialSubtyp return (supertypeName.equals("java.lang.Object") && !potentialSubtypeName.equals("java.lang.Object")) || supertype.equals(superClassOf((ClassType) potentialSubtype)) - || superClassesOf((ClassType) potentialSubtype).contains(supertype) + || incompleteSuperClassesOf((ClassType) potentialSubtype).contains(supertype) || implementedInterfacesOf((ClassType) potentialSubtype).contains(supertype); } else if (potentialSubtype instanceof ArrayType) { // Arrays are subtypes of java.lang.Object, java.io.Serializable and java.lang.Cloneable diff --git a/sootup.java.core/src/main/java/sootup/java/core/views/JavaView.java b/sootup.java.core/src/main/java/sootup/java/core/views/JavaView.java index 682edb9333a..f891055ad5f 100644 --- a/sootup.java.core/src/main/java/sootup/java/core/views/JavaView.java +++ b/sootup.java.core/src/main/java/sootup/java/core/views/JavaView.java @@ -130,11 +130,7 @@ public synchronized Optional getClass(@Nonnull ClassType type) { Optional> abstractClass = getAbstractClass(type); - if (!abstractClass.isPresent()) { - return Optional.empty(); - } - - return buildClassFrom(abstractClass.get()); + return abstractClass.flatMap(this::buildClassFrom); } /** Returns the amount of classes that are currently stored in the cache. */ From 884c62820ba90381069176975b5dfba68333c975 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Tue, 17 Oct 2023 17:48:24 +0200 Subject: [PATCH 34/36] removed unnecessary constructor in MethodHandle --- .../core/jimple/common/constant/MethodHandle.java | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/constant/MethodHandle.java b/sootup.core/src/main/java/sootup/core/jimple/common/constant/MethodHandle.java index fd1792c29e4..f26729b0a8c 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/constant/MethodHandle.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/constant/MethodHandle.java @@ -94,19 +94,7 @@ public MethodHandle( @Nonnull SootClassMemberSignature referenceSignature, int tag, @Nonnull Type type) { - this.kind = Kind.getKind(tag); - this.type = type; - this.referenceSignature = referenceSignature; - if ((this.isMethodRef() && !(referenceSignature instanceof MethodSignature)) - || (this.isFieldRef() && !(referenceSignature instanceof FieldSignature))) { - throw new IllegalArgumentException( - "Tag:" - + tag - + " " - + kind.valStr - + " does not match with the given signature:" - + referenceSignature.getClass()); - } + this(referenceSignature, Kind.getKind(tag), type); } public MethodHandle( From 1ed3ab1a3266190027c42bbd59b6495b0a3fda9f Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Tue, 17 Oct 2023 17:48:40 +0200 Subject: [PATCH 35/36] added tests for MethodHandle --- .../jimple/common/constant/MethodHandle.java | 4 + .../common/constant/MethodHandleTest.java | 114 ++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 sootup.core/src/test/java/sootup/core/jimple/common/constant/MethodHandleTest.java diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/constant/MethodHandle.java b/sootup.core/src/main/java/sootup/core/jimple/common/constant/MethodHandle.java index f26729b0a8c..8c02e3246f8 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/constant/MethodHandle.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/constant/MethodHandle.java @@ -148,6 +148,10 @@ public Type getType() { return type; } + public Kind getKind() { + return kind; + } + public SootClassMemberSignature getReferenceSignature() { return referenceSignature; } diff --git a/sootup.core/src/test/java/sootup/core/jimple/common/constant/MethodHandleTest.java b/sootup.core/src/test/java/sootup/core/jimple/common/constant/MethodHandleTest.java new file mode 100644 index 00000000000..e6db3b602dd --- /dev/null +++ b/sootup.core/src/test/java/sootup/core/jimple/common/constant/MethodHandleTest.java @@ -0,0 +1,114 @@ +package sootup.core.jimple.common.constant; + +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertThrows; + +import categories.Java8Test; +import java.util.Collections; +import junit.framework.TestCase; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import sootup.core.jimple.common.constant.MethodHandle.Kind; +import sootup.core.signatures.FieldSignature; +import sootup.core.signatures.MethodSignature; +import sootup.core.signatures.PackageName; +import sootup.core.types.ClassType; +import sootup.core.types.PrimitiveType.IntType; +import sootup.core.types.VoidType; + +@Category(Java8Test.class) +public class MethodHandleTest extends TestCase { + + @Test + public void testMethodHandle() { + assertEquals(Kind.REF_GET_FIELD.toString(), "REF_GET_FIELD"); + assertEquals(Kind.REF_GET_FIELD.getValueName(), "REF_GET_FIELD"); + assertEquals(Kind.REF_GET_FIELD.getValue(), 1); + + for (Kind currentKind : Kind.values()) { + assertEquals(currentKind, Kind.getKind(currentKind.getValueName())); + assertEquals(currentKind, Kind.getKind(currentKind.getValue())); + } + // not valid kinds + assertThrows(RuntimeException.class, () -> Kind.getKind(0)); + assertThrows(RuntimeException.class, () -> Kind.getKind("invalid")); + + assertTrue(MethodHandle.isMethodRef(Kind.REF_INVOKE_VIRTUAL.getValue())); + assertTrue(MethodHandle.isMethodRef(Kind.REF_INVOKE_STATIC.getValue())); + assertTrue(MethodHandle.isMethodRef(Kind.REF_INVOKE_SPECIAL.getValue())); + assertTrue(MethodHandle.isMethodRef(Kind.REF_INVOKE_CONSTRUCTOR.getValue())); + assertTrue(MethodHandle.isMethodRef(Kind.REF_INVOKE_INTERFACE.getValue())); + assertFalse(MethodHandle.isMethodRef(Kind.REF_GET_FIELD.getValue())); + assertFalse(MethodHandle.isMethodRef(Kind.REF_PUT_FIELD.getValue())); + assertFalse(MethodHandle.isMethodRef(Kind.REF_PUT_FIELD_STATIC.getValue())); + assertFalse(MethodHandle.isMethodRef(Kind.REF_GET_FIELD_STATIC.getValue())); + + assertFalse(MethodHandle.isFieldRef(Kind.REF_INVOKE_VIRTUAL.getValue())); + assertFalse(MethodHandle.isFieldRef(Kind.REF_INVOKE_STATIC.getValue())); + assertFalse(MethodHandle.isFieldRef(Kind.REF_INVOKE_SPECIAL.getValue())); + assertFalse(MethodHandle.isFieldRef(Kind.REF_INVOKE_CONSTRUCTOR.getValue())); + assertFalse(MethodHandle.isFieldRef(Kind.REF_INVOKE_INTERFACE.getValue())); + assertTrue(MethodHandle.isFieldRef(Kind.REF_GET_FIELD.getValue())); + assertTrue(MethodHandle.isFieldRef(Kind.REF_PUT_FIELD.getValue())); + assertTrue(MethodHandle.isFieldRef(Kind.REF_PUT_FIELD_STATIC.getValue())); + assertTrue(MethodHandle.isFieldRef(Kind.REF_GET_FIELD_STATIC.getValue())); + + ClassType classType = + new ClassType() { + @Override + public boolean isBuiltInClass() { + return false; + } + + @Override + public String getFullyQualifiedName() { + return "test.A"; + } + + @Override + public String getClassName() { + return "A"; + } + + @Override + public PackageName getPackageName() { + return new PackageName("test"); + } + }; + MethodSignature ms = + new MethodSignature(classType, "m1", Collections.emptyList(), VoidType.getInstance()); + FieldSignature fs = new FieldSignature(classType, "f", IntType.getInstance()); + + MethodHandle mhms = new MethodHandle(ms, Kind.REF_INVOKE_VIRTUAL.getValue(), classType); + MethodHandle mhfs = new MethodHandle(fs, Kind.REF_GET_FIELD, classType); + + // not valid Method handles + assertThrows( + IllegalArgumentException.class, + () -> new MethodHandle(fs, Kind.REF_INVOKE_CONSTRUCTOR, classType)); + assertThrows( + IllegalArgumentException.class, () -> new MethodHandle(ms, Kind.REF_GET_FIELD, classType)); + + assertTrue(mhms.isMethodRef()); + assertFalse(mhms.isFieldRef()); + + assertFalse(mhfs.isMethodRef()); + assertTrue(mhfs.isFieldRef()); + + assertEquals(mhfs.getType(), classType); + assertEquals( + mhfs.toString(), + "methodhandle: \"" + mhfs.getKind() + "\" " + mhfs.getReferenceSignature()); + + MethodHandle mhms2 = new MethodHandle(ms, Kind.REF_INVOKE_VIRTUAL.getValue(), classType); + assertTrue(mhfs.equals(mhfs)); + assertFalse(mhfs.equals(mhms)); + assertFalse(mhfs.equals(null)); + assertFalse(mhfs.equals(classType)); + assertFalse(mhfs.equals(mhms2)); + + assertEquals(mhfs.hashCode(), mhfs.hashCode()); + assertEquals(mhms.hashCode(), mhms2.hashCode()); + assertNotEquals(mhfs.hashCode(), mhms.hashCode()); + } +} From 1f2614b037961a110f14121a982cdeae8012130f Mon Sep 17 00:00:00 2001 From: Indrale Dnyaneshwar <118615488+Dnyanu76@users.noreply.github.com> Date: Wed, 18 Oct 2023 18:52:54 +0530 Subject: [PATCH 36/36] Remove typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 051d37be1da..5d2b9119d87 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Do you have questions? Feel free to start a [Discussion](https://github.com/soot #### (compared to its predecessor [Soot](https://github.com/soot-oss/soot).) - [x] New Improved API (without Globals/Singletons) - [x] Fully-Parallelizable Architecture -- [x] Enables lazyloading of classes (no interleaved loading of used/dependend classes anymore) +- [x] Enables lazyloading of classes (no interleaved loading of used/dependent classes anymore) - [x] Fail early strategy - input validation while constructing/building objects - [x] Up-to-Date (i.e. Java8!) Sourcecode Frontend - [x] Full Java 21 Support for Bytecode