Skip to content

Commit f12a1ec

Browse files
committed
Simplifying the query.
1 parent 50134e6 commit f12a1ec

File tree

1 file changed

+38
-50
lines changed

1 file changed

+38
-50
lines changed

cpp/ql/src/Likely Bugs/Format/NonConstantFormat.ql

Lines changed: 38 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)