Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9c05ffe

Browse files
committed
C++: Emulate old security library's use of predictable more accurately.
1 parent f4bbdee commit 9c05ffe

1 file changed

Lines changed: 57 additions & 15 deletions

File tree

cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,56 @@ private predicate predictableInstruction(Instruction instr) {
2121
predictableInstruction(instr.(UnaryInstruction).getUnary())
2222
}
2323

24+
/**
25+
* Functions that we should only allow taint to flow through (to the return
26+
* value) if all but the source argument are 'predictable'. This is done to
27+
* emulate the old security library's implementation rather than due to any
28+
* strong belief that this is the right approach.
29+
*
30+
* Note that the list itself is not very principled; it consists of all the
31+
* functions listed in the old security library's [default] `isPureFunction`
32+
* but not in the old taint tracking library's `returnArgument` predicate.
33+
*/
34+
predicate predictableOnlyFlow(string name) {
35+
name = "abs" or
36+
name = "atof" or
37+
name = "atoi" or
38+
name = "atol" or
39+
name = "atoll" or
40+
name = "labs" or
41+
name = "strcasestr" or
42+
//name = "strcat" or
43+
name = "strchnul" or
44+
name = "strchr" or
45+
name = "strchrnul" or
46+
name = "strcmp" or
47+
//name = "strcpy" or
48+
name = "strcspn" or
49+
name = "strdup" or
50+
name = "strlen" or
51+
//name = "strncat" or
52+
name = "strncmp" or
53+
//name = "strncpy" or
54+
name = "strndup" or
55+
name = "strnlen" or
56+
name = "strrchr" or
57+
name = "strspn" or
58+
name = "strstr" or
59+
name = "strtod" or
60+
name = "strtof" or
61+
name = "strtol" or
62+
name = "strtoll" or
63+
name = "strtoq" or
64+
name = "strtoul"
65+
}
66+
2467
private DataFlow::Node getNodeForSource(Expr source) {
2568
isUserInput(source, _) and
2669
(
2770
result = DataFlow::exprNode(source)
2871
or
2972
result = DataFlow::definitionByReferenceNode(source)
3073
)
31-
}
3274

3375
private class DefaultTaintTrackingCfg extends DataFlow::Configuration {
3476
DefaultTaintTrackingCfg() { this = "DefaultTaintTrackingCfg" }
@@ -123,15 +165,16 @@ private predicate nodeIsBarrier(DataFlow::Node node) {
123165

124166
private predicate instructionTaintStep(Instruction i1, Instruction i2) {
125167
// Expressions computed from tainted data are also tainted
126-
i2 =
127-
any(CallInstruction call |
128-
isPureFunction(call.getStaticCallTarget().getName()) and
129-
call.getAnArgument() = i1 and
130-
forall(Instruction arg | arg = call.getAnArgument() | arg = i1 or predictableInstruction(arg)) and
131-
// flow through `strlen` tends to cause dubious results, if the length is
132-
// bounded.
133-
not call.getStaticCallTarget().getName() = "strlen"
134-
)
168+
exists(CallInstruction call, int argIndex | call = i2 |
169+
isPureFunction(call.getStaticCallTarget().getName()) and
170+
i1 = getACallArgumentOrIndirection(call, argIndex) and
171+
forall(Instruction arg | arg = call.getAnArgument() |
172+
arg = getACallArgumentOrIndirection(call, argIndex) or predictableInstruction(arg)
173+
) and
174+
// flow through `strlen` tends to cause dubious results, if the length is
175+
// bounded.
176+
not call.getStaticCallTarget().getName() = "strlen"
177+
)
135178
or
136179
// Flow through pointer dereference
137180
i2.(LoadInstruction).getSourceAddress() = i1
@@ -168,11 +211,11 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
168211
)
169212
or
170213
// Flow from argument to return value
171-
i2 =
172-
any(CallInstruction call |
214+
i2 = any(CallInstruction call |
173215
exists(int indexIn |
174216
modelTaintToReturnValue(call.getStaticCallTarget(), indexIn) and
175-
i1 = getACallArgumentOrIndirection(call, indexIn)
217+
i1 = getACallArgumentOrIndirection(call, indexIn) and
218+
not predictableOnlyFlow(call.getStaticCallTarget().getName())
176219
)
177220
)
178221
or
@@ -181,8 +224,7 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
181224
// together in a single virtual variable.
182225
// TODO: Will this work on the test for `TaintedPath.ql`, where the output arg
183226
// is a pointer addition expression?
184-
i2 =
185-
any(WriteSideEffectInstruction outNode |
227+
i2 = any(WriteSideEffectInstruction outNode |
186228
exists(CallInstruction call, int indexIn, int indexOut |
187229
modelTaintToParameter(call.getStaticCallTarget(), indexIn, indexOut) and
188230
i1 = getACallArgumentOrIndirection(call, indexIn) and

0 commit comments

Comments
 (0)