1
1
import semmle.code.cpp.models.interfaces.ArrayFunction
2
2
import semmle.code.cpp.models.interfaces.Taint
3
+ import semmle.code.cpp.models.interfaces.DataFlow
3
4
import semmle.code.cpp.models.interfaces.Alias
4
5
import semmle.code.cpp.models.interfaces.SideEffect
5
6
@@ -8,7 +9,7 @@ import semmle.code.cpp.models.interfaces.SideEffect
8
9
* guaranteed to be side-effect free.
9
10
*/
10
11
private class PureStrFunction extends AliasFunction , ArrayFunction , TaintFunction ,
11
- SideEffectFunction
12
+ SideEffectFunction , DataFlowFunction
12
13
{
13
14
PureStrFunction ( ) {
14
15
this .hasGlobalOrStdOrBslName ( [
@@ -26,22 +27,43 @@ private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunctio
26
27
}
27
28
28
29
override predicate hasTaintFlow ( FunctionInput input , FunctionOutput output ) {
29
- exists ( ParameterIndex i |
30
+ exists ( ParameterIndex i | exists ( this .getParameter ( i ) ) |
31
+ // For these functions we add taint flow according to the following rules:
32
+ // 1. If the parameter is of a pointer type then there is taint from the
33
+ // indirection of the parameter. Otherwise, there is taint from the
34
+ // parameter.
35
+ // 2. If the return value is of a pointer type then there is taint to the
36
+ // indirection of the return. Otherwise, there is taint to the return.
30
37
(
31
- input .isParameter ( i ) and
32
- exists ( this .getParameter ( i ) )
33
- or
34
- input .isParameterDeref ( i ) and
35
- this .getParameter ( i ) .getUnspecifiedType ( ) instanceof PointerType
38
+ if this .getParameter ( i ) .getUnspecifiedType ( ) instanceof PointerType
39
+ then input .isParameterDeref ( i )
40
+ else input .isParameter ( i )
36
41
) and
37
42
// Functions that end with _l also take a locale argument (always as the last argument),
38
43
// and we don't want taint from those arguments.
39
44
( not this .getName ( ) .matches ( "%\\_l" ) or exists ( this .getParameter ( i + 1 ) ) )
40
45
) and
41
46
(
42
- output .isReturnValueDeref ( ) and
43
- this .getUnspecifiedType ( ) instanceof PointerType
44
- or
47
+ if this .getUnspecifiedType ( ) instanceof PointerType
48
+ then output .isReturnValueDeref ( )
49
+ else output .isReturnValue ( )
50
+ )
51
+ or
52
+ // If there is taint flow from *input to *output then there is also taint
53
+ // flow from input to output.
54
+ this .hasTaintFlow ( input .getIndirectionInput ( ) , output .getIndirectionOutput ( ) ) and
55
+ // no need to add taint-flow if we already have dataflow
56
+ not this .hasDataFlow ( input , output )
57
+ }
58
+
59
+ override predicate hasDataFlow ( FunctionInput input , FunctionOutput output ) {
60
+ exists ( int i |
61
+ input .isParameter ( i ) and
62
+ // see the comment in `hasTaintFlow` for an explanation
63
+ ( not this .getName ( ) .matches ( "%\\_l" ) or exists ( this .getParameter ( i + 1 ) ) ) and
64
+ // These functions always return the same pointer as they are given
65
+ this .hasGlobalOrStdOrBslName ( [ strrev ( ) , strlwr ( ) , strupr ( ) ] ) and
66
+ this .getParameter ( i ) .getUnspecifiedType ( ) instanceof PointerType and
45
67
output .isReturnValue ( )
46
68
)
47
69
}
0 commit comments