Skip to content

Commit f2a9876

Browse files
authored
Merge pull request #2003 from geoffw0/formatarg
CPP: WrongTypeFormatArguments.ql Fix
2 parents d9bdb2c + d434f90 commit f2a9876

File tree

6 files changed

+82
-9
lines changed

6 files changed

+82
-9
lines changed

change-notes/1.23/analysis-cpp.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ The following changes in version 1.23 affect C/C++ analysis in all applications.
2424
| Too many arguments to formatting function (`cpp/too-many-format-arguments`) | Fewer false positive results | Fixed false positives resulting from mistmatching declarations of a formatting function. |
2525
| Unclear comparison precedence (`cpp/comparison-precedence`) | Fewer false positive results | False positives involving template classes and functions have been fixed. |
2626
| Comparison of narrow type with wide type in loop condition (`cpp/comparison-with-wider-type`) | Higher precision | The precision of this query has been increased to "high" as the alerts from this query have proved to be valuable on real-world projects. With this precision, results are now displayed by default in LGTM. |
27+
| Non-constant format string (`cpp/non-constant-format`) | Fewer false positive results | Fixed false positives resulting from mistmatching declarations of a formatting function. |
2728

2829
## Changes to libraries
2930

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

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,32 @@ import semmle.code.cpp.commons.StringAnalysis
88
import semmle.code.cpp.models.interfaces.FormattingFunction
99
import semmle.code.cpp.models.implementations.Printf
1010

11+
class PrintfFormatAttribute extends FormatAttribute {
12+
PrintfFormatAttribute() {
13+
getArchetype() = "printf" or
14+
getArchetype() = "__printf__"
15+
}
16+
}
17+
1118
/**
1219
* A function that can be identified as a `printf` style formatting
1320
* function by its use of the GNU `format` attribute.
1421
*/
1522
class AttributeFormattingFunction extends FormattingFunction {
16-
FormatAttribute printf_attrib;
17-
1823
override string getCanonicalQLClass() { result = "AttributeFormattingFunction" }
1924

2025
AttributeFormattingFunction() {
21-
printf_attrib = getAnAttribute() and
22-
(
23-
printf_attrib.getArchetype() = "printf" or
24-
printf_attrib.getArchetype() = "__printf__"
25-
) and
26-
exists(printf_attrib.getFirstFormatArgIndex()) // exclude `vprintf` style format functions
26+
exists(PrintfFormatAttribute printf_attrib |
27+
printf_attrib = getAnAttribute() and
28+
exists(printf_attrib.getFirstFormatArgIndex()) // exclude `vprintf` style format functions
29+
)
2730
}
2831

29-
override int getFormatParameterIndex() { result = printf_attrib.getFormatIndex() }
32+
override int getFormatParameterIndex() {
33+
forex(PrintfFormatAttribute printf_attrib | printf_attrib = getAnAttribute() |
34+
result = printf_attrib.getFormatIndex()
35+
)
36+
}
3037
}
3138

3239
/**
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
__attribute__((format(printf, 1, 3)))
3+
void myMultiplyDefinedPrintf(const char *format, const char *extraArg, ...)
4+
{
5+
// ...
6+
}
7+
8+
__attribute__((format(printf, 1, 3)))
9+
void myMultiplyDefinedPrintf2(const char *format, const char *extraArg, ...);
10+
11+
char *getString();
12+
13+
void test_custom_printf1()
14+
{
15+
myMultiplyDefinedPrintf("string", getString()); // GOOD
16+
myMultiplyDefinedPrintf(getString(), "string"); // BAD [NOT DETECTED]
17+
myMultiplyDefinedPrintf2("string", getString()); // GOOD (we can't tell which declaration is correct so we have to assume this is OK)
18+
myMultiplyDefinedPrintf2(getString(), "string"); // GOOD (we can't tell which declaration is correct so we have to assume this is OK)
19+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
__attribute__((format(printf, 2, 3)))
3+
void myMultiplyDefinedPrintf(const char *extraArg, const char *format, ...); // this declaration does not match the definition
4+
5+
__attribute__((format(printf, 2, 3)))
6+
void myMultiplyDefinedPrintf2(const char *extraArg, const char *format, ...);
7+
8+
char *getString();
9+
10+
void test_custom_printf2(char *string)
11+
{
12+
myMultiplyDefinedPrintf("string", getString()); // GOOD
13+
myMultiplyDefinedPrintf(getString(), "string"); // BAD [NOT DETECTED]
14+
myMultiplyDefinedPrintf2("string", getString()); // GOOD (we can't tell which declaration is correct so we have to assume this is OK)
15+
myMultiplyDefinedPrintf2(getString(), "string"); // GOOD (we can't tell which declaration is correct so we have to assume this is OK)
16+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
__attribute__((format(printf, 1, 3)))
3+
void myMultiplyDefinedPrintf(const char *format, const char *extraArg, ...)
4+
{
5+
// ...
6+
}
7+
__attribute__((format(printf, 1, 3)))
8+
void myMultiplyDefinedPrintf2(const char *format, const char *extraArg, ...);
9+
10+
void test_custom_printf1()
11+
{
12+
myMultiplyDefinedPrintf("%i", "%f", 1); // GOOD
13+
myMultiplyDefinedPrintf("%i", "%f", 1.0f); // BAD [NOT DETECTED]
14+
myMultiplyDefinedPrintf2("%i", "%f", 1); // GOOD (we can't tell which declaration is correct so we have to assume this is OK)
15+
myMultiplyDefinedPrintf2("%i", "%f", 1.0f); // GOOD (we can't tell which declaration is correct so we have to assume this is OK)
16+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
__attribute__((format(printf, 2, 3)))
3+
void myMultiplyDefinedPrintf(const char *extraArg, const char *format, ...); // this declaration does not match the definition
4+
5+
__attribute__((format(printf, 2, 3)))
6+
void myMultiplyDefinedPrintf2(const char *extraArg, const char *format, ...);
7+
8+
void test_custom_printf2()
9+
{
10+
myMultiplyDefinedPrintf("%i", "%f", 1); // GOOD
11+
myMultiplyDefinedPrintf("%i", "%f", 1.0f); // BAD [NOT DETECTED]
12+
myMultiplyDefinedPrintf2("%i", "%f", 1); // GOOD (we can't tell which declaration is correct so we have to assume this is OK)
13+
myMultiplyDefinedPrintf2("%i", "%f", 1.0f); // GOOD (we can't tell which declaration is correct so we have to assume this is OK)
14+
}

0 commit comments

Comments
 (0)