Skip to content

Commit a8f1d57

Browse files
authored
Merge pull request github#17775 from github/calumgrant/bmn/wrong-type-format-arguments-test
C++: Reduce FPs in cpp/wrong-type-format-argument due to extraction errors
2 parents 226756e + 421413a commit a8f1d57

File tree

22 files changed

+95
-29
lines changed

22 files changed

+95
-29
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
category: feature
3+
---
4+
* Added the predicate `mayBeFromImplicitlyDeclaredFunction()` to the `Call` class to represent calls that may be the return value of an implicitly declared C function.
5+
* Added the predicate `getAnExplicitDeclarationEntry()` to the `Function` class to get a `FunctionDeclarationEntry` that is not implicit.

cpp/ql/lib/semmle/code/cpp/Function.qll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,14 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
230230
)
231231
}
232232

233+
/**
234+
* Gets a non-implicit function declaration entry.
235+
*/
236+
FunctionDeclarationEntry getAnExplicitDeclarationEntry() {
237+
result = this.getADeclarationEntry() and
238+
not result.isImplicit()
239+
}
240+
233241
private predicate declEntry(FunctionDeclarationEntry fde) {
234242
fun_decls(unresolveElement(fde), underlyingElement(this), _, _, _) and
235243
// If one .cpp file specializes a function, and another calls the

cpp/ql/lib/semmle/code/cpp/exprs/Call.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,11 @@ class Call extends Expr, NameQualifiableElement, TCall {
149149
variableAddressEscapesTreeNonConst(va, this.getQualifier().getFullyConverted()) and
150150
i = -1
151151
}
152+
153+
/** Holds if this expression could be the return value of an implicitly declared function. */
154+
predicate mayBeFromImplicitlyDeclaredFunction() {
155+
this.getTarget().getADeclarationEntry().isImplicit()
156+
}
152157
}
153158

154159
/**

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ private class Sprintf extends FormattingFunction, NonThrowingFunction {
9191
override int getFirstFormatArgumentIndex() {
9292
if this.hasName("__builtin___sprintf_chk")
9393
then result = 4
94-
else result = this.getNumberOfParameters()
94+
else result = super.getFirstFormatArgumentIndex()
9595
}
9696
}
9797

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

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,21 @@ 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+
4560
/** Gets the position at which the format parameter occurs. */
4661
abstract int getFormatParameterIndex();
4762

@@ -121,33 +136,7 @@ abstract class FormattingFunction extends ArrayFunction, TaintFunction {
121136
* the first format specifier in the format string. We ignore all
122137
* implicit function definitions.
123138
*/
124-
int getFirstFormatArgumentIndex() {
125-
// The formatting function either has a definition in the snapshot, or all
126-
// `DeclarationEntry`s agree on the number of parameters (otherwise we don't
127-
// really know the correct number)
128-
if this.hasDefinition()
129-
then result = this.getDefinition().getNumberOfParameters()
130-
else result = this.getNumberOfExplicitParameters()
131-
}
132-
133-
/**
134-
* Gets a non-implicit function declaration entry.
135-
*/
136-
private FunctionDeclarationEntry getAnExplicitDeclarationEntry() {
137-
result = this.getADeclarationEntry() and
138-
not result.isImplicit()
139-
}
140-
141-
/**
142-
* Gets the number of parameters, excluding any parameters that have been defined
143-
* from implicit function declarations. If there is some inconsistency in the number
144-
* of parameters, then don't return anything.
145-
*/
146-
private int getNumberOfExplicitParameters() {
147-
forex(FunctionDeclarationEntry fde | fde = this.getAnExplicitDeclarationEntry() |
148-
result = fde.getNumberOfParameters()
149-
)
150-
}
139+
int getFirstFormatArgumentIndex() { result = firstFormatArgumentIndex }
151140

152141
/**
153142
* Gets the position of the buffer size argument, if any.

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ where
170170
) and
171171
not arg.isAffectedByMacro() and
172172
not arg.isFromUninstantiatedTemplate(_) and
173-
not actual.getUnspecifiedType() instanceof ErroneousType
173+
not actual.getUnspecifiedType() instanceof ErroneousType and
174+
not arg.(Call).mayBeFromImplicitlyDeclaredFunction()
174175
select arg,
175176
"This format specifier for type '" + expected.getName() + "' does not match the argument type '" +
176177
actual.getUnspecifiedType().getName() + "'."
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Remove results from the `cpp/wrong-type-format-argument` ("Wrong type of arguments to formatting function") query if the argument is the return value of an implicitly declared function.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
| file://:0:0:0:0 | <error expr> |
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import cpp
2+
3+
from Expr e
4+
where e.getType() instanceof ErroneousType
5+
select e
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
| file://:0:0:0:0 | There was an error during this compilation |
2+
| implicit.cpp:5:5:5:5 | identifier 'g' is undefined |

0 commit comments

Comments
 (0)