@@ -34,6 +34,18 @@ class UncalledFunction extends Function {
3434 }
3535}
3636
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+
3749/**
3850 * Holds if `node` is a non-constant source of data flow.
3951 * This is defined as either:
@@ -44,7 +56,7 @@ class UncalledFunction extends Function {
4456 *
4557 * With exception to `FlowSource` all non-const values have a type that is not const
4658 * (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
4860 * i.e., assuming users did not get non-const data and cast into a const
4961 *
5062 * The latter two cases address identifying standard string manipulation libraries as input sources
@@ -55,18 +67,10 @@ predicate isNonConst(DataFlow::Node node) {
5567 node instanceof FlowSource
5668 or
5769 // 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
6072 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 ( )
7074 )
7175 or
7276 // 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) {
7579 // i.e., functions that with unknown bodies and are not known to define the output through its input
7680 // are considered as possible non-const sources
7781 // 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 ( ) )
11686 )
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 ( ) ]
117105 )
118106}
119107
0 commit comments