Skip to content

Commit 32e532f

Browse files
committed
C++: Some cleanup to avoid conflating the case of a function returning something as a return value, and a function updating one of its arguments.
1 parent 9c51514 commit 32e532f

File tree

1 file changed

+27
-16
lines changed

1 file changed

+27
-16
lines changed

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

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ class UncalledFunction extends Function {
3737
}
3838
}
3939

40+
predicate dataFlowOrTaintFlowFunction(Function func, FunctionOutput output) {
41+
func.(DataFlowFunction).hasDataFlow(_, output) or
42+
func.(TaintFunction).hasTaintFlow(_, output)
43+
}
44+
4045
/**
4146
* Holds if `node` is a non-constant source of data flow for non-const format string detection.
4247
* This is defined as either:
@@ -81,24 +86,30 @@ predicate isNonConst(DataFlow::Node node) {
8186
// i.e., functions that with unknown bodies and are not known to define the output through its input
8287
// are considered as possible non-const sources
8388
// The function's output must also not be const to be considered a non-const source
84-
exists(Function func, CallInstruction call |
85-
// NOTE: could use `Call` getAnArgument() instead of `CallInstruction` but requires two
86-
// variables representing the same call in ordoer to use `callOutput` below.
87-
exists(Expr arg |
88-
call.getPositionalArgumentOperand(_).getDef().getUnconvertedResultExpression() = arg and
89-
arg = node.asDefiningArgument()
89+
(
90+
// Case 1: It's a known dataflow or taintflow function with flow to the return value
91+
exists(Function func, CallInstruction call |
92+
// NOTE: could use `Call` getAnArgument() instead of `CallInstruction` but requires two
93+
// variables representing the same call in ordoer to use `callOutput` below.
94+
call.getUnconvertedResultExpression() = node.asIndirectExpr() and
95+
func = call.getStaticCallTarget() and
96+
not exists(FunctionOutput output |
97+
dataFlowOrTaintFlowFunction(func, output) and
98+
output.isReturnValueDeref() and
99+
node = callOutput(call, output)
100+
)
90101
)
91102
or
92-
call.getUnconvertedResultExpression() = node.asIndirectExpr()
93-
|
94-
func = call.getStaticCallTarget() and
95-
not exists(FunctionOutput output |
96-
// NOTE: we must include dataflow and taintflow. e.g., including only dataflow we will find sprintf
97-
// variant function's output are now possible non-const sources
98-
pragma[only_bind_out](func).(DataFlowFunction).hasDataFlow(_, output) or
99-
pragma[only_bind_out](func).(TaintFunction).hasTaintFlow(_, output)
100-
|
101-
node = callOutput(call, output)
103+
// Case 1: It's a known dataflow or taintflow function with flow to an output parameter
104+
exists(Function func, int i, CallInstruction call |
105+
call.getPositionalArgumentOperand(i).getDef().getUnconvertedResultExpression() =
106+
node.asDefiningArgument() and
107+
func = call.getStaticCallTarget() and
108+
not exists(FunctionOutput output |
109+
dataFlowOrTaintFlowFunction(func, output) and
110+
output.isParameterDeref(i) and
111+
node = callOutput(call, output)
112+
)
102113
)
103114
) and
104115
not exists(Call c |

0 commit comments

Comments
 (0)