Skip to content

Commit ff48ac5

Browse files
committed
C++: exclude printf implementation internals from format string sinks
1 parent 8e19b05 commit ff48ac5

File tree

1 file changed

+20
-1
lines changed

1 file changed

+20
-1
lines changed

cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatString.ql

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,32 @@ import Flow::PathGraph
2323

2424
predicate isSource(FlowSource source, string sourceType) { sourceType = source.getSourceType() }
2525

26+
/**
27+
* Holds if `f` is a printf-like function or a (possibly nested) wrapper
28+
* that forwards a format-string parameter to one.
29+
*
30+
* Functions that *implement* printf-like behaviour (e.g. a custom
31+
* `vsnprintf` variant) internally parse the caller-supplied format string
32+
* and build small, bounded, local format strings such as `"%d"` or `"%ld"`
33+
* for inner `sprintf` calls. Taint that reaches those inner calls via the
34+
* parsed format specifier is not exploitable, so sinks inside such
35+
* functions should be excluded.
36+
*/
37+
private predicate isPrintfImplementation(Function f) {
38+
f instanceof PrintfLikeFunction
39+
or
40+
exists(PrintfLikeFunction printf | printf.wrapperFunction(f, _, _))
41+
}
42+
2643
module Config implements DataFlow::ConfigSig {
2744
predicate isSource(DataFlow::Node node) { isSource(node, _) }
2845

2946
predicate isSink(DataFlow::Node node) {
3047
exists(PrintfLikeFunction printf |
3148
printf.outermostWrapperFunctionCall([node.asExpr(), node.asIndirectExpr()], _)
32-
)
49+
) and
50+
not isPrintfImplementation(node.asExpr().getEnclosingFunction()) and
51+
not isPrintfImplementation(node.asIndirectExpr().getEnclosingFunction())
3352
}
3453

3554
private predicate isArithmeticNonCharType(ArithmeticType type) {

0 commit comments

Comments
 (0)