diff --git a/sootup.jimple.frontend/pom.xml b/sootup.jimple.frontend/pom.xml index 88f68c5dd0b..95f91c55ba8 100644 --- a/sootup.jimple.frontend/pom.xml +++ b/sootup.jimple.frontend/pom.xml @@ -50,13 +50,17 @@ org.soot-oss sootup.java.core - org.antlr antlr4-runtime + + org.soot-oss + sootup.interceptors + + org.junit.jupiter junit-jupiter-api diff --git a/sootup.jimple.frontend/src/main/java/sootup/jimple/frontend/JimpleAnalysisInputLocation.java b/sootup.jimple.frontend/src/main/java/sootup/jimple/frontend/JimpleAnalysisInputLocation.java index 4cbef4bcb89..6d558b20f6e 100644 --- a/sootup.jimple.frontend/src/main/java/sootup/jimple/frontend/JimpleAnalysisInputLocation.java +++ b/sootup.jimple.frontend/src/main/java/sootup/jimple/frontend/JimpleAnalysisInputLocation.java @@ -120,13 +120,13 @@ List walkDirectory( @Nonnull public Collection getClassSources(@Nonnull View view) { return walkDirectory( - path, view.getIdentifierFactory(), new JimpleClassProvider(bodyInterceptors)); + path, view.getIdentifierFactory(), new JimpleClassProvider(bodyInterceptors, view)); } @Override @Nonnull public Optional getClassSource(@Nonnull ClassType type, @Nonnull View view) { - final JimpleClassProvider classProvider = new JimpleClassProvider(bodyInterceptors); + final JimpleClassProvider classProvider = new JimpleClassProvider(bodyInterceptors, view); final String ext = classProvider.getHandledFileType().toString().toLowerCase(); diff --git a/sootup.jimple.frontend/src/main/java/sootup/jimple/frontend/JimpleClassProvider.java b/sootup.jimple.frontend/src/main/java/sootup/jimple/frontend/JimpleClassProvider.java index cc3d8245720..4c3f0702dd0 100644 --- a/sootup.jimple.frontend/src/main/java/sootup/jimple/frontend/JimpleClassProvider.java +++ b/sootup.jimple.frontend/src/main/java/sootup/jimple/frontend/JimpleClassProvider.java @@ -37,16 +37,19 @@ import sootup.core.inputlocation.FileType; import sootup.core.transform.BodyInterceptor; import sootup.core.types.ClassType; +import sootup.core.views.View; /** @author Markus Schmidt */ public class JimpleClassProvider implements ClassProvider { @Nonnull private final List bodyInterceptors; + @Nonnull private final View view; private static final @Nonnull Logger logger = LoggerFactory.getLogger(JimpleClassProvider.class); - public JimpleClassProvider(List bodyInterceptors) { + public JimpleClassProvider(List bodyInterceptors, @Nonnull View view) { this.bodyInterceptors = bodyInterceptors; + this.view = view; } @Override @@ -57,7 +60,7 @@ public Optional createClassSource( final JimpleConverter jimpleConverter = new JimpleConverter(); return Optional.of( jimpleConverter.run( - CharStreams.fromPath(sourcePath), inputlocation, sourcePath, bodyInterceptors)); + CharStreams.fromPath(sourcePath), inputlocation, sourcePath, bodyInterceptors, view)); } catch (IOException | ResolveException e) { logger.warn( "The jimple file of " diff --git a/sootup.jimple.frontend/src/main/java/sootup/jimple/frontend/JimpleConverter.java b/sootup.jimple.frontend/src/main/java/sootup/jimple/frontend/JimpleConverter.java index 29d53d070d5..dc423ead704 100644 --- a/sootup.jimple.frontend/src/main/java/sootup/jimple/frontend/JimpleConverter.java +++ b/sootup.jimple.frontend/src/main/java/sootup/jimple/frontend/JimpleConverter.java @@ -49,6 +49,7 @@ import sootup.core.signatures.SootClassMemberSubSignature; import sootup.core.transform.BodyInterceptor; import sootup.core.types.*; +import sootup.core.views.View; import sootup.java.core.JavaIdentifierFactory; import sootup.java.core.language.JavaJimple; import sootup.jimple.JimpleBaseVisitor; @@ -56,44 +57,30 @@ public class JimpleConverter { - public OverridingClassSource run( - @Nonnull CharStream charStream, - @Nonnull AnalysisInputLocation inputlocation, - @Nonnull Path sourcePath) { - return run(charStream, inputlocation, sourcePath, Collections.emptyList()); - } - public OverridingClassSource run( @Nonnull CharStream charStream, @Nonnull AnalysisInputLocation inputlocation, @Nonnull Path sourcePath, - @Nonnull List bodyInterceptors) { + @Nonnull List bodyInterceptors, + @Nonnull View view) { final JimpleParser jimpleParser = JimpleConverterUtil.createJimpleParser(charStream, sourcePath); jimpleParser.setErrorHandler(new BailErrorStrategy()); - return run(jimpleParser, inputlocation, sourcePath, bodyInterceptors); - } - - public OverridingClassSource run( - @Nonnull JimpleParser parser, - @Nonnull AnalysisInputLocation inputlocation, - @Nonnull Path sourcePath) { - return run(parser, inputlocation, sourcePath, Collections.emptyList()); + return run(jimpleParser, inputlocation, sourcePath, bodyInterceptors, view); } public OverridingClassSource run( @Nonnull JimpleParser parser, @Nonnull AnalysisInputLocation inputlocation, @Nonnull Path sourcePath, - @Nonnull List bodyInterceptors) { - - // FIXME: [ms] apply bodyInterceptors or better: move that logic into View itself! + @Nonnull List bodyInterceptors, + @Nonnull View view) { ClassVisitor classVisitor; try { - classVisitor = new ClassVisitor(sourcePath); + classVisitor = new ClassVisitor(sourcePath, bodyInterceptors, view); classVisitor.visit(parser.file()); } catch (ParseCancellationException ex) { throw new ResolveException("Syntax Error", sourcePath, ex); @@ -119,10 +106,15 @@ private static class ClassVisitor extends JimpleBaseVisitor { @Nonnull private final JimpleConverterUtil util; @Nonnull private final Path path; + @Nonnull private final List bodyInterceptors; + @Nonnull private final View view; - public ClassVisitor(@Nonnull Path path) { + public ClassVisitor( + @Nonnull Path path, @Nonnull List bodyInterceptors, @Nonnull View view) { this.path = path; util = new JimpleConverterUtil(path); + this.bodyInterceptors = bodyInterceptors; + this.view = view; } private ClassType clazz = null; @@ -197,8 +189,31 @@ public Boolean visitFile(@Nonnull JimpleParser.FileContext ctx) { throw new ResolveException( "Method with the same Signature does already exist.", path, m.getPosition()); } - methods.add(m); - + if (m.isConcrete()) { + Body.BodyBuilder bodyBuilder = Body.builder(m.getBody(), m.getModifiers()); + for (BodyInterceptor bodyInterceptor : bodyInterceptors) { + try { + bodyInterceptor.interceptBody(bodyBuilder, view); + bodyBuilder + .getStmtGraph() + .validateStmtConnectionsInGraph(); // TODO: remove in the future ;-) + } catch (Exception e) { + throw new IllegalStateException( + "Failed to apply " + bodyInterceptor + " to " + m.getSignature(), e); + } + } + Body modifiedBody = bodyBuilder.build(); + SootMethod sm = + new SootMethod( + new OverridingBodySource(m.getBodySource()).withBody(modifiedBody), + m.getSignature(), + m.getModifiers(), + m.getExceptionSignatures(), + m.getPosition()); + methods.add(sm); + } else { + methods.add(m); + } } else { final JimpleParser.FieldContext fieldCtx = ctx.member(i).field(); EnumSet modifier = getFieldModifiers(fieldCtx.field_modifier()); diff --git a/sootup.jimple.frontend/src/main/java/sootup/jimple/frontend/JimpleStringAnalysisInputLocation.java b/sootup.jimple.frontend/src/main/java/sootup/jimple/frontend/JimpleStringAnalysisInputLocation.java index 392628b41e1..ff3fac31a46 100644 --- a/sootup.jimple.frontend/src/main/java/sootup/jimple/frontend/JimpleStringAnalysisInputLocation.java +++ b/sootup.jimple.frontend/src/main/java/sootup/jimple/frontend/JimpleStringAnalysisInputLocation.java @@ -37,6 +37,7 @@ import sootup.core.transform.BodyInterceptor; import sootup.core.types.ClassType; import sootup.core.views.View; +import sootup.interceptors.BytecodeBodyInterceptors; /** * This AnalysisInputLocation encapsulates and represents a single Jimple "file" - the contents of @@ -48,41 +49,51 @@ public class JimpleStringAnalysisInputLocation implements AnalysisInputLocation @Nonnull final Path path = Paths.get("only-in-memory.jimple"); @Nonnull final List bodyInterceptors; - @Nonnull private final OverridingClassSource classSource; @Nonnull final SourceType sourceType; + private String jimpleFileContents; public JimpleStringAnalysisInputLocation(@Nonnull String jimpleFileContents) { - this(jimpleFileContents, SourceType.Application, Collections.emptyList()); + this( + jimpleFileContents, + SourceType.Application, + BytecodeBodyInterceptors.Default.getBodyInterceptors()); } public JimpleStringAnalysisInputLocation( @Nonnull String jimpleFileContents, @Nonnull SourceType sourceType, @Nonnull List bodyInterceptors) { + this.jimpleFileContents = jimpleFileContents; this.bodyInterceptors = bodyInterceptors; this.sourceType = sourceType; + } + private OverridingClassSource getOverridingClassSource( + String jimpleFileContents, List bodyInterceptors, View view) { + final @Nonnull OverridingClassSource classSource; try { JimpleConverter jimpleConverter = new JimpleConverter(); classSource = jimpleConverter.run( - CharStreams.fromString(jimpleFileContents), this, path, bodyInterceptors); + CharStreams.fromString(jimpleFileContents), this, path, bodyInterceptors, view); } catch (Exception e) { throw new IllegalArgumentException("No valid Jimple given.", e); } + return classSource; } @Nonnull @Override public Optional getClassSource( @Nonnull ClassType type, @Nonnull View view) { - return Optional.of(classSource); + return Optional.of(getOverridingClassSource(jimpleFileContents, bodyInterceptors, view)); } @Nonnull @Override public Collection getClassSources(@Nonnull View view) { - return Collections.singletonList(classSource); + return Collections.singletonList( + getOverridingClassSource(jimpleFileContents, bodyInterceptors, view)); } @Nonnull @@ -96,9 +107,4 @@ public SourceType getSourceType() { public List getBodyInterceptors() { return bodyInterceptors; } - - @Nonnull - public ClassType getClassType() { - return classSource.getClassType(); - } } diff --git a/sootup.jimple.frontend/src/test/java/resources/jimple/testbodyinterceptorsinjimpleinputlocation/JB_CP.jimple b/sootup.jimple.frontend/src/test/java/resources/jimple/testbodyinterceptorsinjimpleinputlocation/JB_CP.jimple new file mode 100644 index 00000000000..398c2d92981 --- /dev/null +++ b/sootup.jimple.frontend/src/test/java/resources/jimple/testbodyinterceptorsinjimpleinputlocation/JB_CP.jimple @@ -0,0 +1,51 @@ +public class JB_CP extends java.lang.Object +{ + public void () + { + JB_CP r0; + + + r0 := @this: JB_CP; + specialinvoke r0.()>(); + + return; + } + + int tc1() + { + byte b0, b1; + java.io.PrintStream r0; + JB_CP r1; + + + r1 := @this: JB_CP; + b0 = 5; + b1 = b0; + r0 = ; + virtualinvoke r0.(b1); + + return b1; + } + + public static void main(java.lang.String[]) + { + int i0; + java.io.PrintStream r0; + java.lang.String r1; + java.lang.String[] r2; + JB_CP r3, r4; + + + r2 := @parameter0: java.lang.String[]; + r3 = new JB_CP; + specialinvoke r3.()>(); + r4 = r3; + r0 = ; + i0 = virtualinvoke r4.(); + r1 = dynamicinvoke "makeConcatWithConstants" (i0) ("tc1: \u0001"); + virtualinvoke r0.(r1); + + return; + } +} + diff --git a/sootup.jimple.frontend/src/test/java/sootup/jimple/frontend/JimpleAnalysisInputLocationTest.java b/sootup.jimple.frontend/src/test/java/sootup/jimple/frontend/JimpleAnalysisInputLocationTest.java index 006e051b0a5..1f37a6f673f 100644 --- a/sootup.jimple.frontend/src/test/java/sootup/jimple/frontend/JimpleAnalysisInputLocationTest.java +++ b/sootup.jimple.frontend/src/test/java/sootup/jimple/frontend/JimpleAnalysisInputLocationTest.java @@ -4,12 +4,17 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import sootup.core.model.SootClass; +import sootup.core.model.SourceType; import sootup.core.signatures.PackageName; import sootup.core.types.ClassType; +import sootup.interceptors.CopyPropagator; @Tag("Java8") public class JimpleAnalysisInputLocationTest { @@ -97,4 +102,27 @@ public PackageName getPackageName() { final Optional classSource4 = jv2.getClass(classType); assertTrue(classSource4.isPresent()); } + + @Test + public void testIfBodyInterceptorsApplied() { + final String resourceDir = "src/test/java/resources/"; + final JimpleAnalysisInputLocation inputLocation = + new JimpleAnalysisInputLocation( + Paths.get(resourceDir + "/jimple/testbodyinterceptorsinjimpleinputlocation"), + SourceType.Application, + Arrays.asList(new CopyPropagator())); + JimpleView jv1 = new JimpleView(inputLocation); + List applicationClasses = jv1.getClasses().collect(Collectors.toList()); + applicationClasses.forEach( + cls -> { + cls.getMethods() + .forEach( + m -> { + if (m.getSignature().getName().contains("tc1")) { + String s = m.getBody().toString(); + System.out.println(s); + } + }); + }); + } } diff --git a/sootup.jimple.frontend/src/test/java/sootup/jimple/frontend/JimpleConverterTest.java b/sootup.jimple.frontend/src/test/java/sootup/jimple/frontend/JimpleConverterTest.java index 37fa00efb42..2c10cad184e 100644 --- a/sootup.jimple.frontend/src/test/java/sootup/jimple/frontend/JimpleConverterTest.java +++ b/sootup.jimple.frontend/src/test/java/sootup/jimple/frontend/JimpleConverterTest.java @@ -30,8 +30,14 @@ public class JimpleConverterTest { private SootClass parseJimpleClass(CharStream cs) throws ResolveException { JimpleConverter jimpleVisitor = new JimpleConverter(); + EagerInputLocation eagerInputLocation = new EagerInputLocation(); final OverridingClassSource scs = - jimpleVisitor.run(cs, new EagerInputLocation(), Paths.get("")); + jimpleVisitor.run( + cs, + eagerInputLocation, + Paths.get(""), + Collections.emptyList(), + new JimpleView(eagerInputLocation)); return new SootClass(scs, SourceType.Application); } diff --git a/sootup.jimple.frontend/src/test/java/sootup/jimple/frontend/JimpleStringAnalysisInputLocationTest.java b/sootup.jimple.frontend/src/test/java/sootup/jimple/frontend/JimpleStringAnalysisInputLocationTest.java index 5e37cfffbd2..b5ca885c431 100644 --- a/sootup.jimple.frontend/src/test/java/sootup/jimple/frontend/JimpleStringAnalysisInputLocationTest.java +++ b/sootup.jimple.frontend/src/test/java/sootup/jimple/frontend/JimpleStringAnalysisInputLocationTest.java @@ -22,15 +22,16 @@ * #L% */ -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; import java.util.Collections; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; +import sootup.core.model.SourceType; import sootup.core.signatures.MethodSignature; import sootup.core.types.VoidType; import sootup.core.views.View; +import sootup.interceptors.DeadAssignmentEliminator; @Tag("Java8") public class JimpleStringAnalysisInputLocationTest { @@ -39,7 +40,13 @@ public class JimpleStringAnalysisInputLocationTest { public void testInvalidInput() { String methodStr = "This is not Jimple its just a Sentence."; assertThrows( - IllegalArgumentException.class, () -> new JimpleStringAnalysisInputLocation(methodStr)); + IllegalArgumentException.class, + () -> { + JimpleStringAnalysisInputLocation analysisInputLocation = + new JimpleStringAnalysisInputLocation(methodStr); + JimpleView view = new JimpleView(analysisInputLocation); + analysisInputLocation.getClassSources(view); + }); } @Test @@ -54,15 +61,18 @@ public void test() { + "}"; JimpleStringAnalysisInputLocation analysisInputLocation = - new JimpleStringAnalysisInputLocation(methodStr); + new JimpleStringAnalysisInputLocation( + methodStr, + SourceType.Application, + Collections.singletonList(new DeadAssignmentEliminator())); View view = new JimpleView(Collections.singletonList(analysisInputLocation)); - assertTrue(view.getClass(analysisInputLocation.getClassType()).isPresent()); + assertNotNull(view.getIdentifierFactory().getClassType("DummyClass")); MethodSignature methodSig = view.getIdentifierFactory() .getMethodSignature( - analysisInputLocation.getClassType(), + view.getIdentifierFactory().getClassType("DummyClass"), "banana", VoidType.getInstance(), Collections.emptyList());