diff --git a/shared-test-resources/bugfixes/Issue911_Aggregator.class b/shared-test-resources/bugfixes/Issue911_Aggregator.class new file mode 100644 index 00000000000..b62a20586ff Binary files /dev/null and b/shared-test-resources/bugfixes/Issue911_Aggregator.class differ diff --git a/shared-test-resources/bugfixes/Issue911_Aggregator.java b/shared-test-resources/bugfixes/Issue911_Aggregator.java new file mode 100644 index 00000000000..3af63878592 --- /dev/null +++ b/shared-test-resources/bugfixes/Issue911_Aggregator.java @@ -0,0 +1,11 @@ +class Issue911_Aggregator { + void foo(String len) { + byte[] arr; + try { + arr = len.getBytes(); + } catch (Exception e) { + throw new RuntimeException(e); + } + for (byte a : arr) {} + } +} \ No newline at end of file diff --git a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/interceptors/AggregatorTest.java b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/interceptors/AggregatorTest.java index e4847d13a16..92d355bdc1c 100644 --- a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/interceptors/AggregatorTest.java +++ b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/interceptors/AggregatorTest.java @@ -3,8 +3,10 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; +import categories.TestCategories; import java.nio.file.Paths; import java.util.*; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import sootup.core.graph.MutableStmtGraph; import sootup.core.inputlocation.AnalysisInputLocation; @@ -30,6 +32,7 @@ import sootup.java.core.types.JavaClassType; import sootup.java.core.views.JavaView; +@Tag(TestCategories.JAVA_8_CATEGORY) public class AggregatorTest { /** @@ -196,4 +199,25 @@ public void testIssue739() { final Body body = javaSootMethod.getBody(); } } + + @Test + public void testIssue911() { + + AnalysisInputLocation inputLocationB = + new PathBasedAnalysisInputLocation.ClassFileBasedAnalysisInputLocation( + Paths.get("../shared-test-resources/bugfixes/Issue911_Aggregator.class"), + "", + SourceType.Application, + Collections.singletonList(new Aggregator())); + + JavaView view = new JavaView(inputLocationB); + + final ClassType classType = view.getIdentifierFactory().getClassType("Issue911_Aggregator"); + assertTrue(view.getClass(classType).isPresent()); + + for (JavaSootMethod javaSootMethod : + view.getClasses().stream().findFirst().get().getMethods()) { + final Body body = javaSootMethod.getBody(); + } + } } diff --git a/sootup.java.core/src/main/java/sootup/java/core/interceptors/Aggregator.java b/sootup.java.core/src/main/java/sootup/java/core/interceptors/Aggregator.java index c037f1ecd02..94b37b32136 100644 --- a/sootup.java.core/src/main/java/sootup/java/core/interceptors/Aggregator.java +++ b/sootup.java.core/src/main/java/sootup/java/core/interceptors/Aggregator.java @@ -23,6 +23,7 @@ import java.util.*; import javax.annotation.Nonnull; +import sootup.core.graph.BasicBlock; import sootup.core.graph.MutableStmtGraph; import sootup.core.jimple.basic.LValue; import sootup.core.jimple.basic.Local; @@ -36,6 +37,7 @@ import sootup.core.jimple.visitor.ReplaceUseStmtVisitor; import sootup.core.model.Body; import sootup.core.transform.BodyInterceptor; +import sootup.core.types.ClassType; import sootup.core.views.View; /* @@ -192,7 +194,8 @@ public void interceptBody(@Nonnull Body.BodyBuilder builder, @Nonnull View view) Stmt newStmt; final ReplaceUseStmtVisitor replaceVisitor = new ReplaceUseStmtVisitor(val, aggregatee); - // TODO: this try-catch is an awful hack for "ValueBox.canContainValue" -> try to determine + // TODO: this try-catch is an awful way for the former/legacy "ValueBox.canContainValue" -> + // try to determine // a replaceability earlier! try { replaceVisitor.caseAssignStmt(assignStmt); @@ -203,6 +206,31 @@ public void interceptBody(@Nonnull Body.BodyBuilder builder, @Nonnull View view) // have we been able to inline the value into the newStmt? if (stmt != newStmt) { + + // respect trapranges - check if at least the same exceptional flows exist in the block + // where we will assign the value now. + BasicBlock blockOfDefinition = graph.getBlockOf(relevantDef); + BasicBlock blockOfAssignment = graph.getBlockOf(stmt); + if (blockOfDefinition != blockOfAssignment) { + Map exceptionalSuccessors = + blockOfDefinition.getExceptionalSuccessors(); + int matchingTraps = 0; + for (Map.Entry entry : + blockOfAssignment.getExceptionalSuccessors().entrySet()) { + ClassType type = entry.getKey(); + BasicBlock handler = (BasicBlock) entry.getValue(); + if (exceptionalSuccessors.get(type) == handler) { + matchingTraps++; + } + } + + // has the block where we assign now at least the traps which exist in the block of the + // original definition? + if (matchingTraps < exceptionalSuccessors.size()) { + continue; + } + } + graph.replaceNode(stmt, newStmt); if (graph.getStartingStmt() == relevantDef) { Stmt newStartingStmt = builder.getStmtGraph().successors(relevantDef).get(0);