Skip to content

Commit 8e85f24

Browse files
authored
Merge pull request github#17553 from github/calumgrant/bmn/wrong-number-of-format-arguments
C++: Remove FPs in cpp/wrong-number-format-arguments due to BMN
2 parents 7c473c3 + 8967989 commit 8e85f24

File tree

6 files changed

+42
-10
lines changed

6 files changed

+42
-10
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,8 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
651651

652652
/**
653653
* Holds if this declaration is an implicit function declaration, that is,
654-
* where a function is used before it is declared (under older C standards).
654+
* where a function is used before it is declared (under older C standards,
655+
* or when there were parse errors).
655656
*/
656657
predicate isImplicit() { fun_implicit(underlyingElement(this)) }
657658

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

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -118,19 +118,34 @@ abstract class FormattingFunction extends ArrayFunction, TaintFunction {
118118

119119
/**
120120
* Gets the position of the first format argument, corresponding with
121-
* the first format specifier in the format string.
121+
* the first format specifier in the format string. We ignore all
122+
* implicit function definitions.
122123
*/
123124
int getFirstFormatArgumentIndex() {
124-
result = this.getNumberOfParameters() and
125-
// the formatting function either has a definition in the snapshot, or all
125+
// The formatting function either has a definition in the snapshot, or all
126126
// `DeclarationEntry`s agree on the number of parameters (otherwise we don't
127127
// really know the correct number)
128-
(
129-
this.hasDefinition()
130-
or
131-
forall(FunctionDeclarationEntry fde | fde = this.getADeclarationEntry() |
132-
result = fde.getNumberOfParameters()
133-
)
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()
134149
)
135150
}
136151

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Fixed false positives in the `cpp/wrong-number-format-arguments` ("Too few arguments to formatting function") query when the formatting function has been declared implicitly.

cpp/ql/test/query-tests/Likely Bugs/Format/WrongNumberOfFormatArguments/WrongNumberOfFormatArguments.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@
1010
| test.c:15:2:15:7 | call to printf | Format for printf expects 3 arguments but given 2 |
1111
| test.c:19:2:19:7 | call to printf | Format for printf expects 2 arguments but given 1 |
1212
| test.c:29:3:29:8 | call to printf | Format for printf expects 2 arguments but given 1 |
13+
| test.c:53:2:53:10 | call to my_logger | Format for my_logger expects 3 arguments but given 2 |

cpp/ql/test/query-tests/Likely Bugs/Format/WrongNumberOfFormatArguments/custom_printf.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,6 @@ void test_custom_printf2()
4444
printf("", "%i %i", 100, 200); // GOOD
4545
printf("%i %i", "" ); // GOOD
4646
}
47+
48+
extern "C" void my_logger(int param, char *fmt, ...) __attribute__((format(printf, 2, 3))) {}
49+

cpp/ql/test/query-tests/Likely Bugs/Format/WrongNumberOfFormatArguments/test.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,12 @@ void test(int i, const char *str)
4646
printf("%Y", 1, 2); // GOOD (unknown format character, this might be correct)
4747
printf("%1.1Y", 1, 2); // GOOD (unknown format character, this might be correct)
4848
printf("%*.*Y", 1, 2); // GOOD (unknown format character, this might be correct)
49+
50+
// Implicit logger function declaration
51+
my_logger(0, "%i %i %i %i %i %i\n", 1, 2, 3, 4, 5, 6); // GOOD
52+
my_logger(0, "%i %i %i\n", 1, 2, 3); // GOOD
53+
my_logger(0, "%i %i %i\n", 1, 2); // BAD (too few format arguments)
4954
}
55+
56+
// A spurious definition of my_logger
57+
extern void my_logger(int param, char *fmt, int, int, int, int, int);

0 commit comments

Comments
 (0)