-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathtaint.ql
More file actions
141 lines (120 loc) · 4.36 KB
/
taint.ql
File metadata and controls
141 lines (120 loc) · 4.36 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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import utils.test.dataflow.FlowTestCommon
module TaintModels {
class SetMemberFunction extends TaintFunction {
SetMemberFunction() { this.hasName("setMember") }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(0) and
output.isQualifierObject()
}
}
class GetMemberFunction extends TaintFunction {
GetMemberFunction() { this.hasName("getMember") }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierObject() and
output.isReturnValue()
}
}
class SetStringFunction extends TaintFunction {
SetStringFunction() { this.hasName("setString") }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameterDeref(0) and
output.isQualifierObject()
}
}
class GetStringFunction extends TaintFunction {
GetStringFunction() { this.hasName("getString") }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierObject() and
output.isReturnValueDeref()
}
}
}
module AstTest {
private import semmle.code.cpp.dataflow.TaintTracking
private import semmle.code.cpp.models.interfaces.Taint
/** Common data flow configuration to be used by tests. */
module AstTestAllocationConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asExpr().(FunctionCall).getTarget().getName() = "source"
or
source.asParameter().getName().matches("source%")
or
// Track uninitialized variables
exists(source.asUninitialized())
or
exists(FunctionCall fc |
fc.getAnArgument() = source.asDefiningArgument() and
fc.getTarget().hasName("argument_source")
)
}
predicate isSink(DataFlow::Node sink) {
exists(FunctionCall call |
call.getTarget().getName() = "sink" and
sink.asExpr() = call.getAnArgument()
)
}
predicate isBarrier(DataFlow::Node barrier) {
barrier.asExpr().(VariableAccess).getTarget().hasName("sanitizer")
}
}
module AstFlow = TaintTracking::Global<AstTestAllocationConfig>;
}
module IRTest {
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.ir.dataflow.TaintTracking
private import semmle.code.cpp.ir.dataflow.FlowSteps
/**
* Object->field flow when the object is of type
* TaintInheritingContentObject and the field is named
* flowFromObject
*/
class TaintInheritingContentTest extends TaintInheritingContent, DataFlow::FieldContent {
TaintInheritingContentTest() {
exists(Struct o, Field f |
this.getField() = f and
f = o.getAField() and
o.hasGlobalName("TaintInheritingContentObject") and
f.hasName("flowFromObject") and
this.getIndirectionIndex() = 1
)
}
}
/** Common data flow configuration to be used by tests. */
module TestAllocationConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asExpr().(FunctionCall).getTarget().getName() = "source"
or
source.asIndirectExpr().(FunctionCall).getTarget().getName() = "source"
or
source.asIndirectExpr().(FunctionCall).getTarget().getName() = "indirect_source"
or
source.asParameter().getName().matches("source%")
or
exists(FunctionCall fc |
fc.getAnArgument() = source.asDefiningArgument() and
fc.getTarget().hasName("argument_source")
)
}
predicate isSink(DataFlow::Node sink) {
exists(FunctionCall call |
call.getTarget().getName() = "sink" and
[sink.asExpr(), sink.asIndirectExpr()] = call.getAnArgument()
)
or
exists(FunctionCall call |
call.getTarget().getName() = "indirect_sink" and
sink.asIndirectExpr() = call.getAnArgument()
)
}
predicate isBarrier(DataFlow::Node barrier) {
barrier.asExpr().(VariableAccess).getTarget().hasName("sanitizer")
}
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
// allow arbitrary reads at sinks
isSink(node) and
c.(DataFlow::FieldContent).getField().getDeclaringType() = node.getType().getUnspecifiedType()
}
}
module IRFlow = TaintTracking::Global<TestAllocationConfig>;
}
import MakeTest<MergeTests<AstFlowTest<AstTest::AstFlow>, IRFlowTest<IRTest::IRFlow>>>