Skip to content

Generalize the scopes to make them more consistent #149

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
May 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d22b08b
Generalize scope implementations
smeyer198 Apr 26, 2025
0ef5b54
Some clean up
smeyer198 Apr 27, 2025
d9e5e77
Generalize static field handling
smeyer198 Apr 28, 2025
7deaa68
Generalize static field logic in scopes
smeyer198 Apr 28, 2025
2999e6a
Distinguish between defined and phantom methods
smeyer198 Apr 28, 2025
437730a
Small fix
smeyer198 Apr 28, 2025
e3513d4
Get rid of singleton in Opal scope
smeyer198 Apr 29, 2025
521f964
Use Scene as object in Soot scope
smeyer198 Apr 29, 2025
63ed657
Get rid of singleton in SootUp scope
smeyer198 Apr 29, 2025
da4cce5
Make Soot scope consistent
smeyer198 Apr 29, 2025
e413cf6
Make Opal scope consistent
smeyer198 Apr 29, 2025
56b3c5c
Final consistent step
smeyer198 Apr 29, 2025
79ad20e
Use singleton for TRUE and FALSE vals
smeyer198 Apr 29, 2025
f68d899
Fix release job
smeyer198 Apr 29, 2025
e857edc
Some doc to generalized elements
smeyer198 Apr 30, 2025
dbcadd0
Merge branch 'develop' into feature/scope-genralization
smeyer198 Apr 30, 2025
4c46972
Use local directory for JDK classes
smeyer198 Apr 30, 2025
60c36ca
Use interner for phantom methods
smeyer198 May 5, 2025
0fe9c91
Reuse some values
smeyer198 May 5, 2025
72836c5
Use "of" as factory method name of Opal methods
smeyer198 May 5, 2025
3679996
Fix methods in Opal tests
smeyer198 May 5, 2025
eb0f995
Fix method calls
smeyer198 May 5, 2025
5d0558d
Update OpalArrayTest.scala
smeyer198 May 5, 2025
873cd44
Merge branch 'develop' into feature/scope-genralization
swissiety May 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,10 @@ jobs:
fetch-depth: 0

- name: Get latest tag
run: echo "tag=$(git describe --tags --abbrev=0)" >> $GITHUB_OUTPUT
run: echo "tag=$(git describe --tags --abbrev=0)" >> $GITHUB_ENV

- name: Create GitHub release
run: |
gh release create "$TAG"
gh release create ${{ env.tag }} --title ${{ env.tag }} --generate-notes
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ steps.get_tag.outputs.tag }}
79 changes: 46 additions & 33 deletions boomerangPDS/src/main/java/boomerang/WeightedBoomerang.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@
import boomerang.scope.Field;
import boomerang.scope.Field.ArrayField;
import boomerang.scope.FrameworkScope;
import boomerang.scope.IArrayRef;
import boomerang.scope.IInstanceFieldRef;
import boomerang.scope.Method;
import boomerang.scope.Pair;
import boomerang.scope.Statement;
import boomerang.scope.StaticFieldVal;
import boomerang.scope.Val;
Expand Down Expand Up @@ -69,7 +70,6 @@
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sync.pds.solver.SyncPDSSolver.PDSSystem;
Expand Down Expand Up @@ -204,30 +204,38 @@ protected boolean preventFieldTransitionAdd(
private void handleStaticInitializer(
Node<Edge, Val> node, BackwardBoomerangSolver<W> backwardSolver) {
if (options.trackStaticFieldAtEntryPointToClinit()
&& node.fact().isStatic()
&& node.fact().isStatic() // Equivalent to "node.fact() instanceof StaticFieldVal"?
&& node.fact() instanceof StaticFieldVal
&& isFirstStatementOfEntryPoint(node.stmt().getStart())) {
Val fact = node.fact();
Stream<Method> methodStream = frameworkScope.handleStaticFieldInitializers(fact);

methodStream.forEach(
m -> {
if (m.isStaticInitializer()) {
for (Statement ep : icfg.getEndPointsOf(m)) {
StaticFieldVal newVal =
frameworkScope.newStaticFieldVal(((StaticFieldVal) fact).field(), m);
cfg.addPredsOfListener(
new PredecessorListener(ep) {
@Override
public void getPredecessor(Statement pred) {
backwardSolver.addNormalCallFlow(
node, new Node<>(new ControlFlowGraph.Edge(pred, ep), newVal));
backwardSolver.addNormalFieldFlow(
node, new Node<>(new ControlFlowGraph.Edge(pred, ep), newVal));
}
});
}
}
});
StaticFieldVal fact = (StaticFieldVal) node.fact();

/* If we reach the first statement of an entry point method, and we have
* not found the allocation site yet, we extend the dataflow to the static
* initializer method of the fields class
*/
Collection<Method> entryPoints = callGraph.getEntryPoints();
for (Method entryPoint : entryPoints) {
if (!entryPoint.isStaticInitializer()) {
continue;
}

if (entryPoint.getDeclaringClass().equals(fact.getDeclaringClass())) {
Val newVal = fact.withNewMethod(entryPoint);

for (Statement ep : icfg.getEndPointsOf(entryPoint)) {
cfg.addPredsOfListener(
new PredecessorListener(ep) {
@Override
public void getPredecessor(Statement pred) {
backwardSolver.addNormalFieldFlow(
node, new Node<>(new ControlFlowGraph.Edge(pred, ep), newVal));
backwardSolver.addNormalCallFlow(
node, new Node<>(new ControlFlowGraph.Edge(pred, ep), newVal));
}
});
}
}
}
}
}

Expand Down Expand Up @@ -615,17 +623,20 @@ public boolean preventCallRuleAdd(
}

protected FieldWritePOI createArrayFieldStore(Edge s) {
Pair<Val, Integer> base = s.getStart().getArrayBase();
IArrayRef base = s.getStart().getArrayBase();
return fieldWrites.getOrCreate(
new FieldWritePOI(s, base.getX(), Field.array(base.getY()), s.getStart().getRightOp()));
new FieldWritePOI(
s, base.getBase(), Field.array(base.getIndex()), s.getStart().getRightOp()));
}

protected FieldWritePOI createFieldStore(Edge cfgEdge) {
Statement s = cfgEdge.getStart();
Val base = s.getFieldStore().getX();
Field field = s.getFieldStore().getY();
Val stored = s.getRightOp();
return fieldWrites.getOrCreate(new FieldWritePOI(cfgEdge, base, field, stored));

IInstanceFieldRef fieldRef = s.getFieldStore();
Val storedVal = s.getRightOp();

return fieldWrites.getOrCreate(
new FieldWritePOI(cfgEdge, fieldRef.getBase(), fieldRef.getField(), storedVal));
}

protected void forwardHandleFieldWrite(
Expand Down Expand Up @@ -1160,8 +1171,10 @@ private AbstractBoomerangSolver<W> forwardSolve(ForwardQuery query) {
Val var;
Field field;
if (stmt.isFieldStore()) {
field = stmt.getFieldStore().getY();
var = stmt.getFieldStore().getX();
IInstanceFieldRef fieldRef = stmt.getFieldStore();

var = fieldRef.getBase();
field = fieldRef.getField();
forwardHandleFieldWrite(
new Node<>(cfgEdge, stmt.getRightOp()),
new FieldWritePOI(cfgEdge, var, field, stmt.getRightOp()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,12 @@
package boomerang.arrays;

import boomerang.scope.ControlFlowGraph.Edge;
import boomerang.scope.Pair;
import boomerang.scope.Val;
import boomerang.scope.IArrayRef;
import java.util.Set;
import wpds.interfaces.State;

public interface ArrayHandlingStrategy {
void handleForward(Edge arrayStoreStmt, Pair<Val, Integer> arrayBase, Set<State> out);
void handleForward(Edge arrayStoreStmt, IArrayRef arrayBase, Set<State> out);

void handleBackward(Edge arrayStoreStmt, Pair<Val, Integer> arrayBase, Set<State> out);
void handleBackward(Edge arrayStoreStmt, IArrayRef arrayBase, Set<State> out);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@

import boomerang.scope.ControlFlowGraph.Edge;
import boomerang.scope.Field;
import boomerang.scope.Pair;
import boomerang.scope.Val;
import boomerang.scope.IArrayRef;
import java.util.Set;
import sync.pds.solver.SyncPDSSolver.PDSSystem;
import sync.pds.solver.nodes.PushNode;
Expand All @@ -26,12 +25,12 @@
public class ArrayIndexInsensitiveStrategy implements ArrayHandlingStrategy {

@Override
public void handleForward(Edge curr, Pair<Val, Integer> arrayBase, Set<State> out) {
out.add(new PushNode<>(curr, arrayBase.getX(), Field.array(-1), PDSSystem.FIELDS));
public void handleForward(Edge curr, IArrayRef arrayBase, Set<State> out) {
out.add(new PushNode<>(curr, arrayBase.getBase(), Field.array(-1), PDSSystem.FIELDS));
}

@Override
public void handleBackward(Edge curr, Pair<Val, Integer> arrayBase, Set<State> out) {
out.add(new PushNode<>(curr, arrayBase.getX(), Field.array(-1), PDSSystem.FIELDS));
public void handleBackward(Edge curr, IArrayRef arrayBase, Set<State> out) {
out.add(new PushNode<>(curr, arrayBase.getBase(), Field.array(-1), PDSSystem.FIELDS));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@

import boomerang.scope.ControlFlowGraph.Edge;
import boomerang.scope.Field;
import boomerang.scope.Pair;
import boomerang.scope.Val;
import boomerang.scope.IArrayRef;
import java.util.Set;
import sync.pds.solver.SyncPDSSolver.PDSSystem;
import sync.pds.solver.nodes.PushNode;
Expand All @@ -26,14 +25,16 @@
public class ArrayIndexSensitiveStrategy implements ArrayHandlingStrategy {

@Override
public void handleForward(Edge curr, Pair<Val, Integer> arrayBase, Set<State> out) {
public void handleForward(Edge curr, IArrayRef arrayBase, Set<State> out) {
out.add(
new PushNode<>(curr, arrayBase.getX(), Field.array(arrayBase.getY()), PDSSystem.FIELDS));
new PushNode<>(
curr, arrayBase.getBase(), Field.array(arrayBase.getIndex()), PDSSystem.FIELDS));
}

@Override
public void handleBackward(Edge curr, Pair<Val, Integer> arrayBase, Set<State> out) {
public void handleBackward(Edge curr, IArrayRef arrayBase, Set<State> out) {
out.add(
new PushNode<>(curr, arrayBase.getX(), Field.array(arrayBase.getY()), PDSSystem.FIELDS));
new PushNode<>(
curr, arrayBase.getBase(), Field.array(arrayBase.getIndex()), PDSSystem.FIELDS));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,15 @@
package boomerang.arrays;

import boomerang.scope.ControlFlowGraph.Edge;
import boomerang.scope.Pair;
import boomerang.scope.Val;
import boomerang.scope.IArrayRef;
import java.util.Set;
import wpds.interfaces.State;

public class IgnoreArrayStrategy implements ArrayHandlingStrategy {

@Override
public void handleForward(Edge storeStmt, Pair<Val, Integer> storedVal, Set<State> out) {}
public void handleForward(Edge storeStmt, IArrayRef storedVal, Set<State> out) {}

@Override
public void handleBackward(Edge curr, Pair<Val, Integer> arrayBase, Set<State> out) {}
public void handleBackward(Edge curr, IArrayRef arrayBase, Set<State> out) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@

import boomerang.scope.ControlFlowGraph.Edge;
import boomerang.scope.Field;
import boomerang.scope.IArrayRef;
import boomerang.scope.IInstanceFieldRef;
import boomerang.scope.IStaticFieldRef;
import boomerang.scope.InvokeExpr;
import boomerang.scope.Method;
import boomerang.scope.Pair;
import boomerang.scope.Statement;
import boomerang.scope.StaticFieldVal;
import boomerang.scope.Val;
Expand Down Expand Up @@ -121,19 +123,21 @@ public Collection<State> normalFlow(Edge currEdge, Edge nextEdge, Val fact) {
leftSideMatches = true;
if (nextStmt.isFieldLoad()) {
if (options.trackFields()) {
Pair<Val, Field> ifr = nextStmt.getFieldLoad();
if (options.includeInnerClassFields() || !ifr.getY().isInnerClassField()) {
out.add(new PushNode<>(nextEdge, ifr.getX(), ifr.getY(), PDSSystem.FIELDS));
IInstanceFieldRef ifr = nextStmt.getFieldLoad();
if (options.includeInnerClassFields() || !ifr.getField().isInnerClassField()) {
out.add(new PushNode<>(nextEdge, ifr.getBase(), ifr.getField(), PDSSystem.FIELDS));
}
}
} else if (nextStmt.isStaticFieldLoad()) {
IStaticFieldRef staticFieldRef = nextStmt.getStaticField();
if (options.trackFields()) {
strategies
.getStaticFieldStrategy()
.handleBackward(currEdge, nextStmt.getLeftOp(), nextStmt.getStaticField(), out);
.handleBackward(
currEdge, nextStmt.getLeftOp(), staticFieldRef.asStaticFieldVal(), out);
}
} else if (rightOp.isArrayRef()) {
Pair<Val, Integer> arrayBase = nextStmt.getArrayBase();
IArrayRef arrayBase = nextStmt.getArrayBase();
if (options.trackFields()) {
strategies.getArrayHandlingStrategy().handleBackward(nextEdge, arrayBase, out);
}
Expand All @@ -153,23 +157,23 @@ public Collection<State> normalFlow(Edge currEdge, Edge nextEdge, Val fact) {
}
}
if (nextStmt.isFieldStore()) {
Pair<Val, Field> ifr = nextStmt.getFieldStore();
Val base = ifr.getX();
IInstanceFieldRef ifr = nextStmt.getFieldStore();
Val base = ifr.getBase();
if (base.equals(fact)) {
NodeWithLocation<Edge, Val, Field> succNode =
new NodeWithLocation<>(nextEdge, rightOp, ifr.getY());
new NodeWithLocation<>(nextEdge, rightOp, ifr.getField());
out.add(new PopNode<>(succNode, PDSSystem.FIELDS));
}
} else if (nextStmt.isStaticFieldStore()) {
StaticFieldVal staticField = nextStmt.getStaticField();
StaticFieldVal staticField = nextStmt.getStaticField().asStaticFieldVal();
if (fact.isStatic() && fact.equals(staticField)) {
out.add(new Node<>(nextEdge, rightOp));
}
} else if (leftOp.isArrayRef()) {
Pair<Val, Integer> arrayBase = nextStmt.getArrayBase();
if (arrayBase.getX().equals(fact)) {
IArrayRef arrayBase = nextStmt.getArrayBase();
if (arrayBase.getBase().equals(fact)) {
NodeWithLocation<Edge, Val, Field> succNode =
new NodeWithLocation<>(nextEdge, rightOp, Field.array(arrayBase.getY()));
new NodeWithLocation<>(nextEdge, rightOp, Field.array(arrayBase.getIndex()));
out.add(new PopNode<>(succNode, PDSSystem.FIELDS));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
import boomerang.ForwardQuery;
import boomerang.scope.ControlFlowGraph.Edge;
import boomerang.scope.Field;
import boomerang.scope.IArrayRef;
import boomerang.scope.IInstanceFieldRef;
import boomerang.scope.InvokeExpr;
import boomerang.scope.Method;
import boomerang.scope.Pair;
import boomerang.scope.Statement;
import boomerang.scope.StaticFieldVal;
import boomerang.scope.Val;
Expand Down Expand Up @@ -126,19 +127,19 @@ public Set<State> normalFlow(ForwardQuery query, Edge nextEdge, Val fact) {
Val rightOp = nextStmt.getRightOp();
if (rightOp.equals(fact)) {
if (nextStmt.isFieldStore()) {
Pair<Val, Field> ifr = nextStmt.getFieldStore();
IInstanceFieldRef ifr = nextStmt.getFieldStore();
if (options.trackFields()) {
if (options.includeInnerClassFields() || !ifr.getY().isInnerClassField()) {
out.add(new PushNode<>(nextEdge, ifr.getX(), ifr.getY(), PDSSystem.FIELDS));
if (options.includeInnerClassFields() || !ifr.getField().isInnerClassField()) {
out.add(new PushNode<>(nextEdge, ifr.getBase(), ifr.getField(), PDSSystem.FIELDS));
}
}
} else if (nextStmt.isStaticFieldStore()) {
StaticFieldVal sf = nextStmt.getStaticField();
StaticFieldVal sf = nextStmt.getStaticField().asStaticFieldVal();
if (options.trackFields()) {
strategies.getStaticFieldStrategy().handleForward(nextEdge, rightOp, sf, out);
}
} else if (leftOp.isArrayRef()) {
Pair<Val, Integer> arrayBase = nextStmt.getArrayBase();
IArrayRef arrayBase = nextStmt.getArrayBase();
if (options.trackFields()) {
strategies.getArrayHandlingStrategy().handleForward(nextEdge, arrayBase, out);
}
Expand All @@ -147,22 +148,22 @@ public Set<State> normalFlow(ForwardQuery query, Edge nextEdge, Val fact) {
}
}
if (nextStmt.isFieldLoad()) {
Pair<Val, Field> ifr = nextStmt.getFieldLoad();
if (ifr.getX().equals(fact)) {
IInstanceFieldRef ifr = nextStmt.getFieldLoad();
if (ifr.getBase().equals(fact)) {
NodeWithLocation<Edge, Val, Field> succNode =
new NodeWithLocation<>(nextEdge, leftOp, ifr.getY());
new NodeWithLocation<>(nextEdge, leftOp, ifr.getField());
out.add(new PopNode<>(succNode, PDSSystem.FIELDS));
}
} else if (nextStmt.isStaticFieldLoad()) {
StaticFieldVal sf = nextStmt.getStaticField();
StaticFieldVal sf = nextStmt.getStaticField().asStaticFieldVal();
if (fact.isStatic() && fact.equals(sf)) {
out.add(new Node<>(nextEdge, leftOp));
}
} else if (rightOp.isArrayRef()) {
Pair<Val, Integer> arrayBase = nextStmt.getArrayBase();
if (arrayBase.getX().equals(fact)) {
IArrayRef arrayBase = nextStmt.getArrayBase();
if (arrayBase.getBase().equals(fact)) {
NodeWithLocation<Edge, Val, Field> succNode =
new NodeWithLocation<>(nextEdge, leftOp, Field.array(arrayBase.getY()));
new NodeWithLocation<>(nextEdge, leftOp, Field.array(arrayBase.getIndex()));
out.add(new PopNode<>(succNode, PDSSystem.FIELDS));
}
} else if (rightOp.isCast()) {
Expand Down Expand Up @@ -196,13 +197,13 @@ protected boolean killFlow(Statement curr, Val value) {
if (curr.getLeftOp().equals(value)) {
// But not for a statement x = x.f
if (curr.isFieldLoad()) {
Pair<Val, Field> ifr = curr.getFieldLoad();
return !ifr.getX().equals(value);
IInstanceFieldRef ifr = curr.getFieldLoad();
return !ifr.getBase().equals(value);
}
return true;
}
if (curr.isStaticFieldStore()) {
StaticFieldVal sf = curr.getStaticField();
StaticFieldVal sf = curr.getStaticField().asStaticFieldVal();
return value.isStatic() && value.equals(sf);
}
}
Expand Down
Loading