Last active 1 day ago

vaioco revised this gist 1 day ago. Go to revision

3 files changed, 187 insertions

anon.c(file created)

@@ -0,0 +1,56 @@
1 + #pragma QUIC
2 + typedef unsigned int uint;
3 +
4 + struct sconn
5 + {
6 + uint state; /* PERSISTENT to keep state counters correct */
7 + uint unused;
8 + };
9 + typedef struct sconn sconn_t;
10 +
11 + struct container {
12 + sconn_t* conn;
13 + int unused;
14 + };
15 + typedef struct container container_t;
16 + #define STATE0 0
17 + #define STATE1 1
18 + #define STATE2 2
19 +
20 +
21 + sconn_t global = {};
22 +
23 + container_t get_data(){
24 + container_t e = {.conn = &global};
25 + return e;
26 + }
27 +
28 + void sink(sconn_t *conn){
29 + ;;
30 + }
31 +
32 + void set (sconn_t *conn, uint state)
33 + {
34 + conn->state = state;
35 + }
36 +
37 + void set_and_2sched(sconn_t *conn, uint n){
38 + set(conn, STATE0);
39 + sink(conn);
40 + if (n % 2)
41 + set(conn, STATE1);
42 + }
43 +
44 + void easyflow(sconn_t *conn, uint n)
45 + {
46 + if(n%2)
47 + set(conn, STATE2);
48 + set_and_2sched(conn, n);
49 + sink(conn);
50 + }
51 +
52 + void producer(uint n){
53 + container_t c = get_data();
54 + easyflow(c.conn, n);
55 + sink(c.conn);
56 + }

test.ql(file created)

@@ -0,0 +1,18 @@
1 + /**
2 + * @kind path-problem
3 + */
4 +
5 + import cpp
6 + import testlib
7 +
8 + import FlowTest::PathGraph
9 +
10 + query predicate nodes(FlowTest::PathNode n, string key, string val) {
11 + key = "semmle.label" and val = n.toString() + " " + n.getState().(ConnState).toString()
12 + }
13 +
14 + from FlowTest::PathNode source, FlowTest::PathNode sink,
15 + ConnState sig, ConnState sig2
16 + where FlowTest::flowPath(source, sink)
17 + and sig = sink.getState() and sig2 = source.getState()
18 + select sink.getNode(), source, sink, "Unsafe data from sig $@ to sig $@ ", sig2, sig2.toString(), sig, sig.toString()

testlib.qll(file created)

@@ -0,0 +1,113 @@
1 + import cpp
2 + import semmle.code.cpp.dataflow.new.TaintTracking
3 +
4 +
5 + newtype ConnStateType =
6 + STATE0() or
7 + STATE1() or
8 + STATE2()
9 +
10 + predicate allStates(ConnStateType s) {
11 + s =
12 + STATE0() or
13 + s = STATE1()
14 + or s = STATE2()
15 + }
16 +
17 + class ConnState extends ConnStateType {
18 + final string toString() {
19 + this = STATE0() and result = "STATE0"
20 + or
21 + this = STATE1() and result = "STATE1"
22 + or this = STATE2() and result = "STATE2"
23 + }
24 + Location getLocation() { result instanceof UnknownLocation }
25 + }
26 + predicate isSetState(Function m, int arg, ConnState sqt) {
27 + m.getName() = "set"
28 + and (
29 + arg = 0 and sqt = STATE0()
30 + or
31 + arg = 1 and sqt = STATE1()
32 + or
33 + arg = 2 and sqt = STATE2()
34 + )
35 + }
36 + predicate isCallSetState(FunctionCall fc, ConnState sqt) {
37 + isSetState(fc.getTarget(), fc.getArgument(1).getValue().toInt(), sqt)
38 + }
39 +
40 + class ConnFlowStateTransformerNode extends DataFlow::Node {
41 + ConnState next_state;
42 + ConnFlowStateTransformerNode() {
43 + exists(FunctionCall fc|
44 + isCallSetState(fc, next_state )
45 + and this.asIndirectArgument() = fc.getArgument(0)
46 + )
47 + or
48 + exists(FunctionCall fc|
49 + isCallSetState(fc, next_state )
50 + and this.asExpr() = fc.getArgument(0)
51 + )
52 + or
53 + exists(FunctionCall fc|
54 + isCallSetState(fc, next_state )
55 + and this.asDefiningArgument() = fc.getArgument(0)
56 + )
57 + }
58 + ConnState transform(ConnState flowstate){
59 + flowstate != next_state and result = next_state
60 + }
61 + }
62 +
63 + predicate isAdditionalStepImpl(DataFlow::Node n1, DataFlow::Node n2){
64 + // from event to event.conn
65 + exists(FieldAccess fa |
66 + n1.asIndirectExpr() = fa.getQualifier() and
67 + n2.asExpr() = fa
68 + and fa.getTarget().getName() = "conn"
69 + )
70 + or
71 + exists(FieldAccess fa |
72 + n1.asIndirectExpr() = fa.getQualifier() and
73 + n2.asIndirectExpr() = fa
74 + and fa.getTarget().getName() = "conn"
75 + )
76 + }
77 + module TestConfig implements DataFlow::StateConfigSig {
78 + class FlowState = ConnState;
79 + predicate isSource(DataFlow::Node node, FlowState sig) {
80 + exists(FunctionCall fc |
81 + fc.getTarget().getName()= "get_data"
82 + and fc = node.asExpr()
83 + and allStates(sig)
84 + )
85 + }
86 +
87 + predicate isSink(DataFlow::Node sink, FlowState state) {
88 + exists(FunctionCall fc |
89 + fc.getTarget().getName()= "sink"
90 + and fc.getArgument(0) = sink.asExpr()
91 + and allStates(state)
92 + )
93 + }
94 +
95 + predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) {
96 + isAdditionalStepImpl(n1,n2)
97 + }
98 + predicate isAdditionalFlowStep(
99 + DataFlow::Node node1, FlowState prevState, DataFlow::Node node2, FlowState succState
100 + ) {
101 + node2.(ConnFlowStateTransformerNode).transform(prevState) = succState
102 + and DataFlow::simpleLocalFlowStep(node1, node2, _)
103 + }
104 +
105 + predicate isBarrier(DataFlow::Node node, FlowState state) {
106 + node.(ConnFlowStateTransformerNode).transform(state) != state
107 + }
108 + }
109 +
110 + module FlowTest = TaintTracking::GlobalWithState<TestConfig>;
111 + int explorationLimit() { result = 4 }
112 + module MyPartialFlowFwd = FlowTest::FlowExplorationFwd<explorationLimit/0>;
113 +
Newer Older