@@ -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+
2467private 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
3375private class DefaultTaintTrackingCfg extends DataFlow:: Configuration {
3476 DefaultTaintTrackingCfg( ) { this = "DefaultTaintTrackingCfg" }
@@ -123,15 +165,16 @@ private predicate nodeIsBarrier(DataFlow::Node node) {
123165
124166private 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