@@ -34,6 +34,18 @@ class UncalledFunction extends Function {
34
34
}
35
35
}
36
36
37
+ /*
38
+ * const char* means (const char)*, so the pointer is not const, the pointed to value is.
39
+ * Grabs the base type of the underlying type of `t` if `t` is a pointer and checks `isConst()` else
40
+ * checks on the underlying type of `t` alone.
41
+ */
42
+ bindingset [ t]
43
+ predicate hasConstSpecifier ( Type t ) {
44
+ if t .getUnderlyingType ( ) instanceof PointerType
45
+ then t .getUnderlyingType ( ) .( PointerType ) .getBaseType ( ) .isConst ( )
46
+ else t .getUnderlyingType ( ) .isConst ( )
47
+ }
48
+
37
49
/**
38
50
* Holds if `node` is a non-constant source of data flow.
39
51
* This is defined as either:
@@ -44,7 +56,7 @@ class UncalledFunction extends Function {
44
56
*
45
57
* With exception to `FlowSource` all non-const values have a type that is not const
46
58
* (declared without a `const` specifier)
47
- * ASSUMPTION: any const values are assumed to be static if their assignment is not seen (
59
+ * ASSUMPTION: any const values are assumed to be static if their assignment is not seen
48
60
* i.e., assuming users did not get non-const data and cast into a const
49
61
*
50
62
* The latter two cases address identifying standard string manipulation libraries as input sources
@@ -55,18 +67,10 @@ predicate isNonConst(DataFlow::Node node) {
55
67
node instanceof FlowSource
56
68
or
57
69
// Parameters of uncalled functions that aren't const
58
- exists ( UncalledFunction f , Parameter p , Type t |
59
- not t . isConst ( ) and
70
+ exists ( UncalledFunction f , Parameter p |
71
+ not hasConstSpecifier ( p . getType ( ) ) and
60
72
f .getAParameter ( ) = p and
61
- p = node .asParameter ( ) and
62
- not f .getType ( ) .getUnderlyingType ( ) .isConst ( ) and
63
- (
64
- // const char* means (const char)*, so the pointer is not const, the pointed to value is
65
- // Grab the base type if a pointer, as this is the type we will check for const-ness
66
- if p .getType ( ) .getUnderlyingType ( ) instanceof PointerType
67
- then t = p .getType ( ) .getUnderlyingType ( ) .( PointerType ) .getBaseType ( )
68
- else t = p .getType ( ) .getUnderlyingType ( )
69
- )
73
+ p = node .asParameter ( )
70
74
)
71
75
or
72
76
// Consider as an input any out arg of a function or a function's return where the function is not:
@@ -75,45 +79,29 @@ predicate isNonConst(DataFlow::Node node) {
75
79
// i.e., functions that with unknown bodies and are not known to define the output through its input
76
80
// are considered as possible non-const sources
77
81
// The function's output must also not be const to be considered a non-const source
78
- exists ( Type t |
79
- not t .isConst ( ) and
80
- exists ( Call c |
81
- exists ( Expr arg | c .getAnArgument ( ) = arg |
82
- arg = node .asDefiningArgument ( ) and
83
- (
84
- // const char* means (const char)*, so the pointer is not const, the pointed to value is
85
- // Grab the base type if a pointer, as this is the type we will check for const-ness
86
- if arg .getType ( ) .getUnderlyingType ( ) instanceof PointerType
87
- then t = arg .getType ( ) .getUnderlyingType ( ) .( PointerType ) .getBaseType ( )
88
- else t = arg .getType ( ) .getUnderlyingType ( )
89
- )
90
- )
91
- or
92
- c = node .asIndirectExpr ( ) and
93
- (
94
- // const char* means (const char)*, so the pointer is not const, the pointed to value is
95
- // Grab the base type if a pointer, as this is the type we will check for const-ness
96
- if c .getType ( ) .getUnderlyingType ( ) instanceof PointerType
97
- then t = c .getType ( ) .getUnderlyingType ( ) .( PointerType ) .getBaseType ( )
98
- else t = c .getType ( ) .getUnderlyingType ( )
99
- )
100
- ) and
101
- not exists ( Function func , FunctionInput input , FunctionOutput output , CallInstruction call |
102
- // NOTE: we must include dataflow and taintflow. e.g., including only dataflow we will find sprintf
103
- // variant function's output are now possible non-const sources
104
- (
105
- func .( DataFlowFunction ) .hasDataFlow ( input , output ) or
106
- func .( TaintFunction ) .hasTaintFlow ( input , output )
107
- ) and
108
- node = callOutput ( call , output ) and
109
- call .getStaticCallTarget ( ) = func
110
- ) and
111
- not exists ( Call c |
112
- c .getTarget ( ) .hasDefinition ( ) and
113
- if node instanceof DataFlow:: DefinitionByReferenceNode
114
- then c .getAnArgument ( ) = node .asDefiningArgument ( )
115
- else c = [ node .asExpr ( ) , node .asIndirectExpr ( ) ]
82
+ exists ( Call c |
83
+ exists ( Expr arg | c .getAnArgument ( ) = arg |
84
+ arg = node .asDefiningArgument ( ) and
85
+ not hasConstSpecifier ( arg .getType ( ) )
116
86
)
87
+ or
88
+ c = node .asIndirectExpr ( ) and not hasConstSpecifier ( c .getType ( ) )
89
+ ) and
90
+ not exists ( Function func , FunctionInput input , FunctionOutput output , CallInstruction call |
91
+ // NOTE: we must include dataflow and taintflow. e.g., including only dataflow we will find sprintf
92
+ // variant function's output are now possible non-const sources
93
+ (
94
+ func .( DataFlowFunction ) .hasDataFlow ( input , output ) or
95
+ func .( TaintFunction ) .hasTaintFlow ( input , output )
96
+ ) and
97
+ node = callOutput ( call , output ) and
98
+ call .getStaticCallTarget ( ) = func
99
+ ) and
100
+ not exists ( Call c |
101
+ c .getTarget ( ) .hasDefinition ( ) and
102
+ if node instanceof DataFlow:: DefinitionByReferenceNode
103
+ then c .getAnArgument ( ) = node .asDefiningArgument ( )
104
+ else c = [ node .asExpr ( ) , node .asIndirectExpr ( ) ]
117
105
)
118
106
}
119
107
0 commit comments