Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b52ddbf

Browse files
committed
C++: Implement isOutputStream, isOutputString for UserDefinedFormattingFunction as well.
1 parent c3b16a5 commit b52ddbf

2 files changed

Lines changed: 62 additions & 45 deletions

File tree

cpp/ql/src/semmle/code/cpp/commons/Printf.qll

Lines changed: 61 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -34,66 +34,77 @@ class AttributeFormattingFunction extends FormattingFunction {
3434

3535
/**
3636
* A standard function such as `vprintf` that has a format parameter
37-
* and a variable argument list of type `va_arg`.
37+
* and a variable argument list of type `va_arg`. `formatParamIndex` indicates
38+
* the format parameter and `type` indicates the type of `vprintf`:
39+
* - `""` is a `vprintf` variant, `outputParamIndex` is `-1`.
40+
* - `"f"` is a `vfprintf` variant, `outputParamIndex` indicates the output stream parameter.
41+
* - `"s"` is a `vsprintf` variant, `outputParamIndex` indicates the output buffer parameter.
42+
* - `"?"` if the type cannot be deteremined. `outputParamIndex` is `-1`.
3843
*/
39-
predicate primitiveVariadicFormatter(TopLevelFunction f, int formatParamIndex) {
40-
f.getName().regexpMatch("_?_?va?[fs]?n?w?printf(_s)?(_p)?(_l)?") and
44+
predicate primitiveVariadicFormatter(
45+
TopLevelFunction f, string type, int formatParamIndex, int outputParamIndex
46+
) {
47+
type = f.getName().regexpCapture("_?_?va?([fs]?)n?w?printf(_s)?(_p)?(_l)?", 1) and
4148
(
4249
if f.getName().matches("%\\_l")
4350
then formatParamIndex = f.getNumberOfParameters() - 3
4451
else formatParamIndex = f.getNumberOfParameters() - 2
45-
)
46-
}
47-
48-
/**
49-
* A standard function such as `vsprintf` that has an output parameter
50-
* and a variable argument list of type `va_arg`.
51-
*/
52-
private predicate primitiveVariadicFormatterOutput(TopLevelFunction f, int outputParamIndex) {
53-
// note: this might look like the regular expression in `primitiveVariadicFormatter`, but
54-
// there is one important difference: the [fs] part is not optional, as these classify
55-
// the `printf` variants that write to a buffer.
56-
// Conveniently, these buffer parameters are all at index 0.
57-
f.getName().regexpMatch("_?_?va?[fs]n?w?printf(_s)?(_p)?(_l)?") and outputParamIndex = 0
52+
) and
53+
if type = "" then outputParamIndex = -1 else outputParamIndex = 0 // Conveniently, these buffer parameters are all at index 0.
5854
}
5955

60-
private predicate callsVariadicFormatter(Function f, int formatParamIndex) {
61-
exists(FunctionCall fc, int i |
62-
variadicFormatter(fc.getTarget(), i) and
56+
private predicate callsVariadicFormatter(
57+
Function f, string type, int formatParamIndex, int outputParamIndex
58+
) {
59+
// calls a variadic formatter with `formatParamIndex`, `outputParamIndex` linked
60+
exists(FunctionCall fc, int format, int output |
61+
variadicFormatter(fc.getTarget(), type, format, output) and
6362
fc.getEnclosingFunction() = f and
64-
fc.getArgument(i) = f.getParameter(formatParamIndex).getAnAccess()
63+
fc.getArgument(format) = f.getParameter(formatParamIndex).getAnAccess() and
64+
fc.getArgument(output) = f.getParameter(outputParamIndex).getAnAccess()
6565
)
66-
}
67-
68-
private predicate callsVariadicFormatterOutput(Function f, int outputParamIndex) {
69-
exists(FunctionCall fc, int i |
66+
or
67+
// calls a variadic formatter with only `formatParamIndex` linked
68+
exists(FunctionCall fc, string calledType, int format, int output |
69+
variadicFormatter(fc.getTarget(), calledType, format, output) and
7070
fc.getEnclosingFunction() = f and
71-
variadicFormatterOutput(fc.getTarget(), i) and
72-
fc.getArgument(i) = f.getParameter(outputParamIndex).getAnAccess()
71+
fc.getArgument(format) = f.getParameter(formatParamIndex).getAnAccess() and
72+
not fc.getArgument(output) = f.getParameter(_).getAnAccess() and
73+
(
74+
(
75+
calledType = "" and
76+
type = ""
77+
) or (
78+
calledType != "" and
79+
type = "?" // we probably should have an `outputParamIndex` link but have lost it.
80+
)
81+
) and
82+
outputParamIndex = -1
7383
)
7484
}
7585

7686
/**
77-
* Holds if `f` is a function such as `vprintf` that takes variable argument list
78-
* of type `va_arg` and writes formatted output to a buffer given as a parameter at
79-
* index `outputParamIndex`, if any.
87+
* Holds if `f` is a function such as `vprintf` that has a format parameter
88+
* and a variable argument list of type `va_arg`. `formatParamIndex` indicates
89+
* the format parameter and `type` indicates the type of `vprintf`:
90+
* - `""` is a `vprintf` variant, `outputParamIndex` is `-1`.
91+
* - `"f"` is a `vfprintf` variant, `outputParamIndex` indicates the output stream parameter.
92+
* - `"s"` is a `vsprintf` variant, `outputParamIndex` indicates the output buffer parameter.
93+
* - `"?"` if the type cannot be deteremined. `outputParamIndex` is `-1`.
8094
*/
81-
private predicate variadicFormatterOutput(Function f, int outputParamIndex) {
82-
primitiveVariadicFormatterOutput(f, outputParamIndex)
95+
predicate variadicFormatter(Function f, string type, int formatParamIndex, int outputParamIndex) {
96+
primitiveVariadicFormatter(f, type, formatParamIndex, outputParamIndex)
8397
or
8498
not f.isVarargs() and
85-
callsVariadicFormatterOutput(f, outputParamIndex)
99+
callsVariadicFormatter(f, type, formatParamIndex, outputParamIndex)
86100
}
87101

88-
/**
89-
* Holds if `f` is a function such as `vprintf` that has a format parameter
90-
* (at `formatParamIndex`) and a variable argument list of type `va_arg`.
91-
*/
92-
predicate variadicFormatter(Function f, int formatParamIndex) {
93-
primitiveVariadicFormatter(f, formatParamIndex)
94-
or
95-
not f.isVarargs() and
96-
callsVariadicFormatter(f, formatParamIndex)
102+
deprecated predicate primitiveVariadicFormatter(TopLevelFunction f, int formatParamIndex) {
103+
primitiveVariadicFormatter(f, _, formatParamIndex, _)
104+
}
105+
106+
deprecated predicate variadicFormatter(Function f, int formatParamIndex) {
107+
variadicFormatter(f, _, formatParamIndex, _)
97108
}
98109

99110
/**
@@ -103,11 +114,17 @@ predicate variadicFormatter(Function f, int formatParamIndex) {
103114
class UserDefinedFormattingFunction extends FormattingFunction {
104115
override string getAPrimaryQlClass() { result = "UserDefinedFormattingFunction" }
105116

106-
UserDefinedFormattingFunction() { isVarargs() and callsVariadicFormatter(this, _) }
117+
UserDefinedFormattingFunction() { isVarargs() and callsVariadicFormatter(this, _, _, _) }
118+
119+
override int getFormatParameterIndex() { callsVariadicFormatter(this, _, result, _) }
120+
121+
override int getOutputParameterIndex() {
122+
callsVariadicFormatter(this, _, _, result) and not result = -1
123+
}
107124

108-
override int getFormatParameterIndex() { callsVariadicFormatter(this, result) }
125+
override predicate isOutputGlobal() { callsVariadicFormatter(this, "", _, _) }
109126

110-
override int getOutputParameterIndex() { callsVariadicFormatterOutput(this, result) }
127+
override predicate isOutputStream() { callsVariadicFormatter(this, "f", _, _) }
111128
}
112129

113130
/**

cpp/ql/src/semmle/code/cpp/security/PrintfLike.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ predicate printfLikeFunction(Function func, int formatArg) {
1717
formatArg = func.(FormattingFunction).getFormatParameterIndex() and
1818
not func instanceof UserDefinedFormattingFunction
1919
or
20-
primitiveVariadicFormatter(func, formatArg)
20+
primitiveVariadicFormatter(func, _, formatArg, _)
2121
or
2222
exists(ExternalData data |
2323
// TODO Do this \ to / conversion in the toolchain?

0 commit comments

Comments
 (0)