forked from github/codeql
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest.ql
More file actions
84 lines (72 loc) · 2.73 KB
/
test.ql
File metadata and controls
84 lines (72 loc) · 2.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/**
* @kind path-problem
*/
import java
import semmle.code.java.dataflow.DataFlow
import DataFlow
MethodCall propagateCall(string state) {
result.getMethod().getName() = "propagateState" and
state = result.getArgument(1).(StringLiteral).getValue()
}
module TestConfig implements StateConfigSig {
class FlowState = string;
predicate isSource(Node n, FlowState state) {
n.asExpr().(MethodCall).getMethod().getName() = "source" and state = ["A", "B"]
}
predicate isSink(Node n, FlowState state) {
n.asExpr() = any(MethodCall acc | acc.getMethod().getName() = "sink").getAnArgument() and
state = ["A", "B"]
}
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
exists(MethodCall call |
call = propagateCall(state1) and
state2 = state1 and
node1.asExpr() = call.getArgument(0) and
node2.asExpr() = call
)
}
}
module TestFlow = DataFlow::GlobalWithState<TestConfig>;
module Graph = DataFlow::DeduplicatePathGraph<TestFlow::PathNode, TestFlow::PathGraph>;
/**
* Holds if `node` is reachable from a call to `propagateState` with the given `state` argument.
* `call` indicates if a call step was taken (i.e. into a subpath).
*
* We use this to check if one `propagateState` can flow out of another, which is not allowed.
*/
predicate reachableFromPropagate(Graph::PathNode node, string state, boolean call) {
node.getNode().asExpr() = propagateCall(state) and call = false
or
exists(Graph::PathNode prev | reachableFromPropagate(prev, state, call) |
Graph::edges(prev, node, _, _) and
not Graph::subpaths(prev, node, _, _) // argument-passing edges are handled separately
or
Graph::subpaths(prev, _, _, node) // arg -> out (should be included in 'edges' but handle the case here for clarity)
)
or
exists(Graph::PathNode prev |
reachableFromPropagate(prev, state, _) and
Graph::subpaths(prev, node, _, _) and // arg -> parameter
call = true
)
or
exists(Graph::PathNode prev |
reachableFromPropagate(prev, state, call) and
Graph::subpaths(_, _, prev, node) and // return -> out
call = false
)
}
/**
* Holds if `node` is the return value of a `propagateState` call that appears to be reachable
* with a different state than the one propagated by the call, indicating spurious flow resulting from
* merging path nodes.
*/
query predicate spuriousFlow(Graph::PathNode node, string state1, string state2) {
reachableFromPropagate(node, state1, _) and
node.getNode().asExpr() = propagateCall(state2) and
state1 != state2
}
import Graph::PathGraph
from Graph::PathNode source, Graph::PathNode sink
where TestFlow::flowPath(source.getAnOriginalPathNode(), sink.getAnOriginalPathNode())
select source, source, sink, "Flow"