Skip to content

Commit 6f293af

Browse files
committed
C++: Make it possible for 'getFirstFormatArgumentIndex' to sometimes have no result.
1 parent 01bb0ab commit 6f293af

2 files changed

Lines changed: 31 additions & 16 deletions

File tree

cpp/ql/lib/semmle/code/cpp/models/implementations/Printf.qll

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,23 @@ import semmle.code.cpp.models.interfaces.Alias
1010
import semmle.code.cpp.models.interfaces.SideEffect
1111
import semmle.code.cpp.models.interfaces.NonThrowing
1212

13+
/**
14+
* A formatting function that takes its format arguments through a `va_list` parameter.
15+
*/
16+
abstract private class VaListFormattingFunction extends FormattingFunction {
17+
final override int getFirstFormatArgumentIndex() { none() }
18+
19+
final int getVaListParameterIndex() { result = this.getNumberOfParameters() - 1 }
20+
21+
private predicate hasLocaleParameter() { this.getName().matches("%\\_l") }
22+
23+
final override int getFormatParameterIndex() {
24+
if this.hasLocaleParameter()
25+
then result = this.getVaListParameterIndex() - 2
26+
else result = this.getVaListParameterIndex() - 1
27+
}
28+
}
29+
1330
/**
1431
* The standard functions `printf`, `wprintf` and their glib variants.
1532
*/

cpp/ql/lib/semmle/code/cpp/models/interfaces/FormattingFunction.qll

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,21 +42,6 @@ private Type getAFormatterWideTypeOrDefault() {
4242
* A standard library function that uses a `printf`-like formatting string.
4343
*/
4444
abstract class FormattingFunction extends ArrayFunction, TaintFunction {
45-
int firstFormatArgumentIndex;
46-
47-
FormattingFunction() {
48-
firstFormatArgumentIndex > 0 and
49-
if this.hasDefinition()
50-
then firstFormatArgumentIndex = this.getDefinition().getNumberOfParameters()
51-
else
52-
if this instanceof BuiltInFunction
53-
then firstFormatArgumentIndex = this.getNumberOfParameters()
54-
else
55-
forex(FunctionDeclarationEntry fde | fde = this.getAnExplicitDeclarationEntry() |
56-
firstFormatArgumentIndex = fde.getNumberOfParameters()
57-
)
58-
}
59-
6045
/** Gets the position at which the format parameter occurs. */
6146
abstract int getFormatParameterIndex();
6247

@@ -135,8 +120,21 @@ abstract class FormattingFunction extends ArrayFunction, TaintFunction {
135120
* Gets the position of the first format argument, corresponding with
136121
* the first format specifier in the format string. We ignore all
137122
* implicit function definitions.
123+
*
124+
* There is no result if the formatting function takes a `va_list` argument.
138125
*/
139-
int getFirstFormatArgumentIndex() { result = firstFormatArgumentIndex }
126+
int getFirstFormatArgumentIndex() {
127+
result > 0 and
128+
if this.hasDefinition()
129+
then result = this.getDefinition().getNumberOfParameters()
130+
else
131+
if this instanceof BuiltInFunction
132+
then result = this.getNumberOfParameters()
133+
else
134+
forex(FunctionDeclarationEntry fde | fde = this.getAnExplicitDeclarationEntry() |
135+
result = fde.getNumberOfParameters()
136+
)
137+
}
140138

141139
/**
142140
* Gets the position of the buffer size argument, if any.

0 commit comments

Comments
 (0)