Skip to content

Commit 72b691b

Browse files
authored
Merge pull request #233 from secure-software-engineering/feature/method-chaining
Add flow functions that support method chaining
2 parents 4f59f5a + 6738bfe commit 72b691b

10 files changed

+522
-12
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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 typestate;
16+
17+
import boomerang.flowfunction.DefaultBackwardFlowFunction;
18+
import boomerang.options.IAllocationSite;
19+
import boomerang.scope.ControlFlowGraph;
20+
import boomerang.scope.DeclaredMethod;
21+
import boomerang.scope.InvokeExpr;
22+
import boomerang.scope.Statement;
23+
import boomerang.scope.Val;
24+
import boomerang.solver.Strategies;
25+
import boomerang.utils.MethodWrapper;
26+
import java.util.Collection;
27+
import java.util.LinkedHashSet;
28+
import sync.pds.solver.nodes.Node;
29+
import wpds.interfaces.State;
30+
31+
public class ChainingBackwardFlowFunction extends DefaultBackwardFlowFunction {
32+
33+
private final Collection<MethodWrapper> methodChains;
34+
35+
public ChainingBackwardFlowFunction(
36+
IAllocationSite allocationSite,
37+
Strategies strategies,
38+
Collection<MethodWrapper> methodChains) {
39+
super(allocationSite, strategies);
40+
41+
this.methodChains = methodChains;
42+
}
43+
44+
@Override
45+
public Collection<State> callToReturnFlow(
46+
ControlFlowGraph.Edge currEdge, ControlFlowGraph.Edge nextEdge, Val fact) {
47+
Collection<State> out = new LinkedHashSet<>(super.callToReturnFlow(currEdge, nextEdge, fact));
48+
49+
Statement statement = nextEdge.getTarget();
50+
if (statement.isAssignStmt() && statement.containsInvokeExpr()) {
51+
InvokeExpr invokeExpr = statement.getInvokeExpr();
52+
DeclaredMethod declaredMethod = invokeExpr.getDeclaredMethod();
53+
54+
if (methodChains.contains(declaredMethod.toMethodWrapper())) {
55+
Val leftOp = statement.getLeftOp();
56+
57+
if (leftOp.equals(fact) && invokeExpr.isInstanceInvokeExpr()) {
58+
out.add(new Node<>(nextEdge, invokeExpr.getBase()));
59+
}
60+
}
61+
}
62+
63+
return out;
64+
}
65+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
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 typestate;
16+
17+
import boomerang.flowfunction.DefaultFlowFunctionFactory;
18+
import boomerang.flowfunction.IBackwardFlowFunction;
19+
import boomerang.flowfunction.IForwardFlowFunction;
20+
import boomerang.options.BoomerangOptions;
21+
import boomerang.scope.FrameworkScope;
22+
import boomerang.solver.BackwardBoomerangSolver;
23+
import boomerang.solver.ForwardBoomerangSolver;
24+
import boomerang.solver.Strategies;
25+
import boomerang.utils.MethodWrapper;
26+
import java.util.Collection;
27+
28+
/**
29+
* Flow function factory that extends the {@link DefaultFlowFunctionFactory} by adding features to
30+
* deal with chained methods when applying the call-to-return flow. Intermediate representations
31+
* transform chained method calls into multiple statements and introduce new locals for each
32+
* intermediate call. Although the chained calls return the original objects (i.e. an alias), the
33+
* default flow function do not find the aliases. The extension in this flow function factory adds
34+
* the functionality to collect corresponding aliases, too.
35+
*
36+
* <p>For example, a program
37+
*
38+
* <pre>{@code
39+
* l.chain().chain();
40+
* }</pre>
41+
*
42+
* is transformed into the intermediate representation
43+
*
44+
* <pre>{@code
45+
* $s0 = l.chain();
46+
* $s1 = $s0.chain();
47+
* }</pre>
48+
*
49+
* The extended flow functions make sure to collect $s0 and $s1 as alias s.t. the analysis can
50+
* collect the second call to chain().
51+
*/
52+
public class ChainingFlowFunctionFactory extends DefaultFlowFunctionFactory {
53+
54+
private final Collection<MethodWrapper> methodChains;
55+
56+
public ChainingFlowFunctionFactory(Collection<MethodWrapper> methodChains) {
57+
this.methodChains = methodChains;
58+
}
59+
60+
@Override
61+
public IForwardFlowFunction createForwardFlowFunction(
62+
FrameworkScope frameworkScope, BoomerangOptions options, ForwardBoomerangSolver<?> solver) {
63+
Strategies strategies = createStrategies(frameworkScope, options, solver);
64+
65+
return new ChainingForwardFlowFunction(strategies, methodChains);
66+
}
67+
68+
@Override
69+
public IBackwardFlowFunction createBackwardFlowFunction(
70+
FrameworkScope frameworkScope, BoomerangOptions options, BackwardBoomerangSolver<?> solver) {
71+
Strategies strategies = createStrategies(frameworkScope, options, solver);
72+
73+
return new ChainingBackwardFlowFunction(options.allocationSite(), strategies, methodChains);
74+
}
75+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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 typestate;
16+
17+
import boomerang.ForwardQuery;
18+
import boomerang.flowfunction.DefaultForwardFlowFunction;
19+
import boomerang.scope.ControlFlowGraph;
20+
import boomerang.scope.DeclaredMethod;
21+
import boomerang.scope.InvokeExpr;
22+
import boomerang.scope.Statement;
23+
import boomerang.scope.Val;
24+
import boomerang.solver.Strategies;
25+
import boomerang.utils.MethodWrapper;
26+
import java.util.Collection;
27+
import java.util.LinkedHashSet;
28+
import sync.pds.solver.nodes.Node;
29+
import wpds.interfaces.State;
30+
31+
public class ChainingForwardFlowFunction extends DefaultForwardFlowFunction {
32+
33+
private final Collection<MethodWrapper> methodChains;
34+
35+
public ChainingForwardFlowFunction(
36+
Strategies strategies, Collection<MethodWrapper> methodChains) {
37+
super(strategies);
38+
39+
this.methodChains = methodChains;
40+
}
41+
42+
@Override
43+
public Collection<State> callToReturnFlow(
44+
ForwardQuery query, ControlFlowGraph.Edge edge, Val fact) {
45+
Collection<State> out = new LinkedHashSet<>(super.callToReturnFlow(query, edge, fact));
46+
47+
Statement statement = edge.getStart();
48+
if (statement.isAssignStmt() && statement.containsInvokeExpr()) {
49+
InvokeExpr invokeExpr = statement.getInvokeExpr();
50+
DeclaredMethod declaredMethod = invokeExpr.getDeclaredMethod();
51+
52+
if (methodChains.contains(declaredMethod.toMethodWrapper())) {
53+
/* If the current statement is a chained method call, consider it as an alias and
54+
* continue the propagation with the implicitly defined local
55+
*/
56+
if (invokeExpr.isInstanceInvokeExpr()) {
57+
Val base = invokeExpr.getBase();
58+
59+
if (base.equals(fact)) {
60+
out.add(new Node<>(edge, statement.getLeftOp()));
61+
}
62+
}
63+
}
64+
}
65+
66+
return out;
67+
}
68+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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 chains;
16+
17+
public class Chain {
18+
19+
public Chain chain1() {
20+
return this;
21+
}
22+
23+
public Chain chain2() {
24+
return this;
25+
}
26+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
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 chains;
16+
17+
import boomerang.WeightedForwardQuery;
18+
import boomerang.scope.ControlFlowGraph;
19+
import java.util.Collection;
20+
import java.util.Collections;
21+
import typestate.TransitionFunction;
22+
import typestate.finiteautomata.MatcherTransition;
23+
import typestate.finiteautomata.State;
24+
import typestate.finiteautomata.TypeStateMachineWeightFunctions;
25+
26+
public class ChainStateMachine extends TypeStateMachineWeightFunctions {
27+
28+
public enum States implements State {
29+
INIT,
30+
CHAIN1,
31+
CHAIN2;
32+
33+
@Override
34+
public boolean isErrorState() {
35+
return this != CHAIN2;
36+
}
37+
38+
@Override
39+
public boolean isInitialState() {
40+
return this == INIT;
41+
}
42+
43+
@Override
44+
public boolean isAccepting() {
45+
return this == CHAIN2;
46+
}
47+
}
48+
49+
public ChainStateMachine() {
50+
addTransition(
51+
new MatcherTransition(
52+
States.INIT,
53+
".*chain1.*",
54+
MatcherTransition.Parameter.This,
55+
States.CHAIN1,
56+
MatcherTransition.Type.OnCallToReturn));
57+
addTransition(
58+
new MatcherTransition(
59+
States.CHAIN1,
60+
".chain1.*",
61+
MatcherTransition.Parameter.This,
62+
States.CHAIN1,
63+
MatcherTransition.Type.OnCallToReturn));
64+
addTransition(
65+
new MatcherTransition(
66+
States.CHAIN1,
67+
".*chain2.*",
68+
MatcherTransition.Parameter.This,
69+
States.CHAIN2,
70+
MatcherTransition.Type.OnCallToReturn));
71+
addTransition(
72+
new MatcherTransition(
73+
States.CHAIN2,
74+
".chain1.*",
75+
MatcherTransition.Parameter.This,
76+
States.CHAIN1,
77+
MatcherTransition.Type.OnCallToReturn));
78+
addTransition(
79+
new MatcherTransition(
80+
States.CHAIN2,
81+
".chain2.*",
82+
MatcherTransition.Parameter.This,
83+
States.CHAIN2,
84+
MatcherTransition.Type.OnCallToReturn));
85+
}
86+
87+
@Override
88+
public Collection<WeightedForwardQuery<TransitionFunction>> generateSeed(
89+
ControlFlowGraph.Edge stmt) {
90+
try {
91+
return generateAtAllocationSiteOf(stmt, Class.forName(Chain.class.getName()));
92+
} catch (ClassNotFoundException e) {
93+
return Collections.emptySet();
94+
}
95+
}
96+
97+
@Override
98+
protected State initialState() {
99+
return States.INIT;
100+
}
101+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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 chains;
16+
17+
import boomerang.utils.MethodWrapper;
18+
import java.util.Set;
19+
import typestate.ChainingFlowFunctionFactory;
20+
21+
public class ChainingTestFlowFunctionFactory extends ChainingFlowFunctionFactory {
22+
23+
public ChainingTestFlowFunctionFactory() {
24+
super(
25+
Set.of(
26+
new MethodWrapper(Chain.class.getName(), "chain1", Chain.class.getName()),
27+
new MethodWrapper(Chain.class.getName(), "chain2", Chain.class.getName())));
28+
}
29+
}

0 commit comments

Comments
 (0)