Skip to content

Commit 260d5b0

Browse files
committed
Add field and context sensitivity to options
1 parent df99e42 commit 260d5b0

File tree

8 files changed

+184
-13
lines changed

8 files changed

+184
-13
lines changed

SynchronizedPDS/src/main/java/sync/pds/solver/SyncPDSSolver.java

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.Map;
2828
import java.util.Map.Entry;
2929
import java.util.Set;
30+
import org.slf4j.Logger;
3031
import org.slf4j.LoggerFactory;
3132
import sync.pds.solver.nodes.ExclusionNode;
3233
import sync.pds.solver.nodes.GeneratedState;
@@ -58,9 +59,7 @@ public enum PDSSystem {
5859
CALLS
5960
}
6061

61-
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(SyncPDSSolver.class);
62-
private static final boolean FieldSensitive = true;
63-
private static final boolean ContextSensitive = true;
62+
private static final Logger logger = LoggerFactory.getLogger(SyncPDSSolver.class);
6463
protected final WeightedPushdownSystem<Stmt, INode<Fact>, W> callingPDS =
6564
new WeightedPushdownSystem<Stmt, INode<Fact>, W>() {
6665
public String toString() {
@@ -81,6 +80,8 @@ public String toString() {
8180
reachedStateUpdateListeners = HashMultimap.create();
8281
protected final WeightedPAutomaton<Field, INode<Node<Stmt, Fact>>, W> fieldAutomaton;
8382
protected final WeightedPAutomaton<Stmt, INode<Fact>, W> callAutomaton;
83+
private final boolean fieldSensitive;
84+
private final boolean contextSensitive;
8485

8586
protected boolean preventFieldTransitionAdd(
8687
Transition<Field, INode<Node<Stmt, Fact>>> trans, W weight) {
@@ -99,8 +100,33 @@ public SyncPDSSolver(
99100
int maxCallDepth,
100101
int maxFieldDepth,
101102
int maxUnbalancedCallDepth) {
103+
this(
104+
useCallSummaries,
105+
callSummaries,
106+
useFieldSummaries,
107+
fieldSummaries,
108+
maxCallDepth,
109+
maxFieldDepth,
110+
maxUnbalancedCallDepth,
111+
true,
112+
true);
113+
}
114+
115+
public SyncPDSSolver(
116+
final boolean useCallSummaries,
117+
NestedWeightedPAutomatons<Stmt, INode<Fact>, W> callSummaries,
118+
final boolean useFieldSummaries,
119+
NestedWeightedPAutomatons<Field, INode<Node<Stmt, Fact>>, W> fieldSummaries,
120+
int maxCallDepth,
121+
int maxFieldDepth,
122+
int maxUnbalancedCallDepth,
123+
boolean fieldSensitive,
124+
boolean contextSensitive) {
125+
this.fieldSensitive = fieldSensitive;
126+
this.contextSensitive = contextSensitive;
127+
102128
fieldAutomaton =
103-
new WeightedPAutomaton<Field, INode<Node<Stmt, Fact>>, W>() {
129+
new WeightedPAutomaton<>() {
104130
@Override
105131
public INode<Node<Stmt, Fact>> createState(INode<Node<Stmt, Fact>> d, Field loc) {
106132
if (loc.equals(emptyField())) return d;
@@ -141,7 +167,7 @@ public boolean isGeneratedState(INode<Node<Stmt, Fact>> d) {
141167
};
142168

143169
callAutomaton =
144-
new WeightedPAutomaton<Stmt, INode<Fact>, W>() {
170+
new WeightedPAutomaton<>() {
145171
@Override
146172
public INode<Fact> createState(INode<Fact> d, Stmt loc) {
147173
return generateCallState(d, loc);
@@ -556,7 +582,7 @@ public void processPop(Node<Stmt, Fact> curr, PopNode popNode) {
556582
Object location = popNode.location();
557583
if (system.equals(PDSSystem.FIELDS)) {
558584
NodeWithLocation<Stmt, Fact, Field> node = (NodeWithLocation) location;
559-
if (FieldSensitive) {
585+
if (fieldSensitive) {
560586
addFieldRule(
561587
new PopRule<>(
562588
asFieldFact(curr),
@@ -568,7 +594,7 @@ public void processPop(Node<Stmt, Fact> curr, PopNode popNode) {
568594
}
569595
addNormalCallFlow(curr, node.fact());
570596
} else if (system.equals(PDSSystem.CALLS)) {
571-
if (ContextSensitive) {
597+
if (contextSensitive) {
572598
addCallRule(
573599
new PopRule<>(
574600
wrap(curr.fact()), curr.stmt(), wrap((Fact) location), getCallWeights().pop(curr)));
@@ -657,7 +683,7 @@ public void processPush(
657683
Node<Stmt, Fact> curr, Location location, PushNode<Stmt, Fact, ?> succ, PDSSystem system) {
658684
if (system.equals(PDSSystem.FIELDS)) {
659685

660-
if (FieldSensitive) {
686+
if (fieldSensitive) {
661687
addFieldRule(
662688
new PushRule<>(
663689
asFieldFact(curr),
@@ -673,7 +699,7 @@ public void processPush(
673699

674700
} else if (system.equals(PDSSystem.CALLS)) {
675701
addNormalFieldFlow(curr, succ);
676-
if (ContextSensitive) {
702+
if (contextSensitive) {
677703
addCallRule(
678704
new PushRule<>(
679705
wrap(curr.fact()),

boomerangPDS/src/main/java/boomerang/options/BoomerangOptions.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,14 @@ public int maxUnbalancedCallDepth() {
117117
return builder.maxUnbalancedCallDepth;
118118
}
119119

120+
public boolean isFieldSensitive() {
121+
return builder.fieldSensitivity;
122+
}
123+
124+
public boolean isContextSensitive() {
125+
return builder.contextSensitivity;
126+
}
127+
120128
public boolean onTheFlyCallGraph() {
121129
return builder.onTheFlyCallGraph;
122130
}
@@ -167,6 +175,8 @@ public static class OptionsBuilder {
167175
private int maxCallDepth;
168176
private int maxUnbalancedCallDepth;
169177

178+
private boolean fieldSensitivity;
179+
private boolean contextSensitivity;
170180
private boolean onTheFlyCallGraph;
171181
private boolean onTheFlyControlFlow;
172182
private boolean callSummaries;
@@ -190,6 +200,8 @@ protected OptionsBuilder() {
190200
this.maxCallDepth = -1;
191201
this.maxUnbalancedCallDepth = -1;
192202

203+
this.fieldSensitivity = true;
204+
this.contextSensitivity = true;
193205
this.onTheFlyCallGraph = false;
194206
this.onTheFlyControlFlow = false;
195207
this.callSummaries = false;
@@ -277,6 +289,16 @@ public OptionsBuilder withMaxUnbalancedCallDepth(int maxUnbalancedCallDepth) {
277289
return this;
278290
}
279291

292+
public OptionsBuilder enableFieldSensitivity(boolean fieldSensitivity) {
293+
this.fieldSensitivity = fieldSensitivity;
294+
return this;
295+
}
296+
297+
public OptionsBuilder enableContextSensitivity(boolean contextSensitivity) {
298+
this.contextSensitivity = contextSensitivity;
299+
return this;
300+
}
301+
280302
public OptionsBuilder enableOnTheFlyCallGraph(boolean onTheFlyCallGraph) {
281303
this.onTheFlyCallGraph = onTheFlyCallGraph;
282304
return this;

boomerangPDS/src/main/java/boomerang/solver/AbstractBoomerangSolver.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,9 @@ public AbstractBoomerangSolver(
114114
fieldSummaries,
115115
options.maxCallDepth(),
116116
options.maxFieldDepth(),
117-
options.maxUnbalancedCallDepth());
117+
options.maxUnbalancedCallDepth(),
118+
options.isFieldSensitive(),
119+
options.isContextSensitive());
118120
this.options = options;
119121
this.icfg = icfg;
120122
this.cfg = cfg;

boomerangPDS/src/test/java/test/options/OptionsTestInterceptor.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,11 @@ private BoomerangOptions createBoomerangOptions(TestOptions testOptions) {
8585
testOptions.trackStaticFieldAtEntryPointToClinit())
8686
.withMaxFieldDepth(testOptions.maxFieldDepth())
8787
.withMaxCallDepth(testOptions.maxCallDepth())
88+
.withAnalysisTimeout(testOptions.timeout())
89+
.enableFieldSensitivity(testOptions.fieldSensitivity())
90+
.enableContextSensitivity(testOptions.contextSensitivity())
8891
.enableCallSummaries(testOptions.callSummaries())
8992
.enableFieldSummaries(testOptions.fieldSummaries())
90-
.withAnalysisTimeout(testOptions.timeout())
9193
.build();
9294
}
9395
}

boomerangPDS/src/test/java/test/options/TestOptions.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,13 @@ Strategies.StaticFieldStrategy staticFieldStrategy() default
4040

4141
int maxCallDepth() default -1;
4242

43+
int timeout() default -1;
44+
45+
boolean fieldSensitivity() default true;
46+
47+
boolean contextSensitivity() default true;
48+
4349
boolean callSummaries() default false;
4450

4551
boolean fieldSummaries() default false;
46-
47-
int timeout() default -1;
4852
}

boomerangPDS/src/test/java/test/options/boomerang/BoomerangOptionsTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ public void settingOptionsTest() {
6161
BoomerangOptions.builder().withMaxUnbalancedCallDepth(1).build();
6262
Assertions.assertEquals(maxUnbalancedCallDepth.maxUnbalancedCallDepth(), 1);
6363

64+
BoomerangOptions fieldSensitivity =
65+
BoomerangOptions.builder().enableFieldSensitivity(false).build();
66+
Assertions.assertFalse(fieldSensitivity.isFieldSensitive());
67+
68+
BoomerangOptions contextSensitivity =
69+
BoomerangOptions.builder().enableContextSensitivity(false).build();
70+
Assertions.assertFalse(contextSensitivity.isContextSensitive());
71+
6472
BoomerangOptions onTheFlyCallGraph =
6573
BoomerangOptions.builder().enableOnTheFlyCallGraph(true).build();
6674
Assertions.assertTrue(onTheFlyCallGraph.onTheFlyCallGraph());
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* *****************************************************************************
3+
* Copyright (c) 2018 Fraunhofer IEM, Paderborn, Germany
4+
* <p>
5+
* This program and the accompanying materials are made available under the
6+
* terms of the Eclipse Public License 2.0 which is available at
7+
* http://www.eclipse.org/legal/epl-2.0.
8+
* <p>
9+
* SPDX-License-Identifier: EPL-2.0
10+
* <p>
11+
* Contributors:
12+
* Johannes Spaeth - initial API and implementation
13+
* *****************************************************************************
14+
*/
15+
package test.options.boomerang;
16+
17+
import org.junit.jupiter.api.Disabled;
18+
import org.junit.jupiter.api.Test;
19+
import org.junit.jupiter.api.extension.ExtendWith;
20+
import test.options.OptionAssertions;
21+
import test.options.OptionsTestInterceptor;
22+
import test.options.TestOptions;
23+
24+
@Disabled("TODO Does not seem to work correctly")
25+
@ExtendWith(OptionsTestInterceptor.class)
26+
public class ContextSensitivityTest {
27+
28+
@Test
29+
@TestOptions(expectedAllocSites = {"first"})
30+
public void positiveContextSensitivityTest() {
31+
ClassWithField c1 = new ClassWithField();
32+
ClassWithField c2 = new ClassWithField();
33+
setField(c1, "first");
34+
setField(c2, "second");
35+
OptionAssertions.queryFor(c1.field);
36+
}
37+
38+
@Test
39+
@TestOptions(
40+
expectedAllocSites = {"first", "second"},
41+
contextSensitivity = false)
42+
public void negativeContextSensitivityTest() {
43+
ClassWithField c1 = new ClassWithField();
44+
ClassWithField c2 = new ClassWithField();
45+
setField(c1, "first");
46+
setField(c2, "second");
47+
OptionAssertions.queryFor(c1.field);
48+
}
49+
50+
private static void setField(ClassWithField c, String s) {
51+
c.field = s;
52+
}
53+
54+
private static class ClassWithField {
55+
private String field;
56+
}
57+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* *****************************************************************************
3+
* Copyright (c) 2018 Fraunhofer IEM, Paderborn, Germany
4+
* <p>
5+
* This program and the accompanying materials are made available under the
6+
* terms of the Eclipse Public License 2.0 which is available at
7+
* http://www.eclipse.org/legal/epl-2.0.
8+
* <p>
9+
* SPDX-License-Identifier: EPL-2.0
10+
* <p>
11+
* Contributors:
12+
* Johannes Spaeth - initial API and implementation
13+
* *****************************************************************************
14+
*/
15+
package test.options.boomerang;
16+
17+
import org.junit.jupiter.api.Test;
18+
import org.junit.jupiter.api.extension.ExtendWith;
19+
import test.options.OptionAssertions;
20+
import test.options.OptionsTestInterceptor;
21+
import test.options.TestOptions;
22+
23+
@ExtendWith(OptionsTestInterceptor.class)
24+
public class FieldSensitivityTest {
25+
26+
@Test
27+
@TestOptions(expectedAllocSites = {"safe"})
28+
public void positiveFieldSensitivityTest() {
29+
ClassWithFields c = new ClassWithFields();
30+
c.field1 = "safe";
31+
c.field2 = "unsafe";
32+
OptionAssertions.queryFor(c.field1);
33+
}
34+
35+
@Test
36+
@TestOptions(
37+
expectedAllocSites = {"safe", "unsafe", "null"},
38+
fieldSensitivity = false)
39+
public void negativeFieldSensitivityTest() {
40+
ClassWithFields c = new ClassWithFields();
41+
c.field1 = "safe";
42+
c.field2 = "unsafe";
43+
OptionAssertions.queryFor(c.field2);
44+
}
45+
46+
private static class ClassWithFields {
47+
private String field1;
48+
private String field2;
49+
}
50+
}

0 commit comments

Comments
 (0)