11import semmle.code.cpp.models.interfaces.ArrayFunction
22import semmle.code.cpp.models.interfaces.Taint
3+ import semmle.code.cpp.models.interfaces.DataFlow
34import semmle.code.cpp.models.interfaces.Alias
45import semmle.code.cpp.models.interfaces.SideEffect
56
@@ -8,7 +9,7 @@ import semmle.code.cpp.models.interfaces.SideEffect
89 * guaranteed to be side-effect free.
910 */
1011private class PureStrFunction extends AliasFunction , ArrayFunction , TaintFunction ,
11- SideEffectFunction
12+ SideEffectFunction , DataFlowFunction
1213{
1314 PureStrFunction ( ) {
1415 this .hasGlobalOrStdOrBslName ( [
@@ -26,22 +27,43 @@ private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunctio
2627 }
2728
2829 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.
3037 (
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 )
3641 ) and
3742 // Functions that end with _l also take a locale argument (always as the last argument),
3843 // and we don't want taint from those arguments.
3944 ( not this .getName ( ) .matches ( "%\\_l" ) or exists ( this .getParameter ( i + 1 ) ) )
4045 ) and
4146 (
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
4567 output .isReturnValue ( )
4668 )
4769 }
0 commit comments