Skip to content

Commit

Permalink
Merge pull request #1123 from soot-oss/1110-bug-jimple-frontend-does-…
Browse files Browse the repository at this point in the history
…not-apply-specified-interceptors

1110 bug jimple frontend does not apply specified interceptors
  • Loading branch information
swissiety authored Nov 15, 2024
2 parents 68dd0e8 + d1c5e82 commit dec694a
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 45 deletions.
6 changes: 5 additions & 1 deletion sootup.jimple.frontend/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,17 @@
<groupId>org.soot-oss</groupId>
<artifactId>sootup.java.core</artifactId>
</dependency>

<!-- https://mvnrepository.com/artifact/org.antlr/antlr4-runtime -->
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
</dependency>

<dependency>
<groupId>org.soot-oss</groupId>
<artifactId>sootup.interceptors</artifactId>
</dependency>

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,13 @@ List<SootClassSource> walkDirectory(
@Nonnull
public Collection<SootClassSource> getClassSources(@Nonnull View view) {
return walkDirectory(
path, view.getIdentifierFactory(), new JimpleClassProvider(bodyInterceptors));
path, view.getIdentifierFactory(), new JimpleClassProvider(bodyInterceptors, view));
}

@Override
@Nonnull
public Optional<SootClassSource> 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();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<BodyInterceptor> bodyInterceptors;
@Nonnull private final View view;

private static final @Nonnull Logger logger = LoggerFactory.getLogger(JimpleClassProvider.class);

public JimpleClassProvider(List<BodyInterceptor> bodyInterceptors) {
public JimpleClassProvider(List<BodyInterceptor> bodyInterceptors, @Nonnull View view) {
this.bodyInterceptors = bodyInterceptors;
this.view = view;
}

@Override
Expand All @@ -57,7 +60,7 @@ public Optional<SootClassSource> 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 "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,51 +49,38 @@
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;
import sootup.jimple.JimpleParser;

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<BodyInterceptor> bodyInterceptors) {
@Nonnull List<BodyInterceptor> 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<BodyInterceptor> bodyInterceptors) {

// FIXME: [ms] apply bodyInterceptors or better: move that logic into View itself!
@Nonnull List<BodyInterceptor> 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);
Expand All @@ -119,10 +106,15 @@ private static class ClassVisitor extends JimpleBaseVisitor<Boolean> {

@Nonnull private final JimpleConverterUtil util;
@Nonnull private final Path path;
@Nonnull private final List<BodyInterceptor> bodyInterceptors;
@Nonnull private final View view;

public ClassVisitor(@Nonnull Path path) {
public ClassVisitor(
@Nonnull Path path, @Nonnull List<BodyInterceptor> bodyInterceptors, @Nonnull View view) {
this.path = path;
util = new JimpleConverterUtil(path);
this.bodyInterceptors = bodyInterceptors;
this.view = view;
}

private ClassType clazz = null;
Expand Down Expand Up @@ -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<FieldModifier> modifier = getFieldModifiers(fieldCtx.field_modifier());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -48,41 +49,51 @@ public class JimpleStringAnalysisInputLocation implements AnalysisInputLocation

@Nonnull final Path path = Paths.get("only-in-memory.jimple");
@Nonnull final List<BodyInterceptor> 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<BodyInterceptor> bodyInterceptors) {
this.jimpleFileContents = jimpleFileContents;
this.bodyInterceptors = bodyInterceptors;
this.sourceType = sourceType;
}

private OverridingClassSource getOverridingClassSource(
String jimpleFileContents, List<BodyInterceptor> 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<? extends SootClassSource> getClassSource(
@Nonnull ClassType type, @Nonnull View view) {
return Optional.of(classSource);
return Optional.of(getOverridingClassSource(jimpleFileContents, bodyInterceptors, view));
}

@Nonnull
@Override
public Collection<? extends SootClassSource> getClassSources(@Nonnull View view) {
return Collections.singletonList(classSource);
return Collections.singletonList(
getOverridingClassSource(jimpleFileContents, bodyInterceptors, view));
}

@Nonnull
Expand All @@ -96,9 +107,4 @@ public SourceType getSourceType() {
public List<BodyInterceptor> getBodyInterceptors() {
return bodyInterceptors;
}

@Nonnull
public ClassType getClassType() {
return classSource.getClassType();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
public class JB_CP extends java.lang.Object
{
public void <init>()
{
JB_CP r0;


r0 := @this: JB_CP;
specialinvoke r0.<java.lang.Object: void <init>()>();

return;
}

int tc1()
{
byte b0, b1;
java.io.PrintStream r0;
JB_CP r1;


r1 := @this: JB_CP;
b0 = 5;
b1 = b0;
r0 = <java.lang.System: java.io.PrintStream out>;
virtualinvoke r0.<java.io.PrintStream: void println(int)>(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.<JB_CP: void <init>()>();
r4 = r3;
r0 = <java.lang.System: java.io.PrintStream out>;
i0 = virtualinvoke r4.<JB_CP: int tc1()>();
r1 = dynamicinvoke "makeConcatWithConstants" <java.lang.String (int)>(i0) <java.lang.invoke.StringConcatFactory: java.lang.invoke.CallSite makeConcatWithConstants(java.lang.invoke.MethodHandles$Lookup,java.lang.String,java.lang.invoke.MethodType,java.lang.String,java.lang.Object[])>("tc1: \u0001");
virtualinvoke r0.<java.io.PrintStream: void println(java.lang.String)>(r1);

return;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -97,4 +102,27 @@ public PackageName getPackageName() {
final Optional<SootClass> 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<SootClass> 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);
}
});
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
Loading

0 comments on commit dec694a

Please sign in to comment.