Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions change-notes/1.21/analysis-cpp.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@
| Resource not released in destructor (`cpp/resource-not-released-in-destructor`) | Fewer false positive results | Resource allocation and deallocation functions are now determined more accurately. |
| Comparison result is always the same | Fewer false positive results | The range analysis library is now more conservative about floating point values being possibly `NaN` |
| Wrong type of arguments to formatting function (`cpp/wrong-type-format-argument`) | More correct results and fewer false positive results | This query now more accurately identifies wide and non-wide string/character format arguments on different platforms. Platform detection has also been made more accurate for the purposes of this query. |
| Wrong type of arguments to formatting function (`cpp/wrong-type-format-argument`) | Fewer false positive results | Non-standard uses of %L are now understood. |

## Changes to QL libraries
10 changes: 4 additions & 6 deletions cpp/ql/src/semmle/code/cpp/commons/Printf.qll
Original file line number Diff line number Diff line change
Expand Up @@ -572,9 +572,8 @@ class FormatLiteral extends Literal {
((len="hh" and result instanceof IntType)
or (len="h" and result instanceof IntType)
or (len="l" and result = this.getLongType())
or ((len="ll" or len="q")
or ((len="ll" or len="L" or len="q")
and result instanceof LongLongType)
or (len="L" and result instanceof IntType) // doesn't affect integral conversion
or (len="j" and result = this.getIntmax_t())
or ((len="z" or len="Z")
and (result = this.getSize_t() or result = this.getSsize_t()))
Expand All @@ -599,9 +598,8 @@ class FormatLiteral extends Literal {
((len="hh" and result instanceof CharType)
or (len="h" and result instanceof ShortType)
or (len="l" and result = this.getLongType())
or ((len="ll" or len="q")
or ((len="ll" or len="L" or len="q")
and result instanceof LongLongType)
or (len="L" and result instanceof IntType) // doesn't affect integral conversion
or (len="j" and result = this.getIntmax_t())
or ((len="z" or len="Z")
and (result = this.getSize_t() or result = this.getSsize_t()))
Expand All @@ -622,7 +620,7 @@ class FormatLiteral extends Literal {
*/
FloatingPointType getFloatingPointConversion(int n) {
exists(string len | len = this.getLength(n) and
if len="L" then
if (len="L" or len="ll") then
result instanceof LongDoubleType
else
result instanceof DoubleType)
Expand All @@ -638,7 +636,7 @@ class FormatLiteral extends Literal {
(len="hh" and base instanceof CharType)
or (len="h" and base instanceof ShortType)
or (len="l" and base = this.getLongType())
or (len="ll" and base instanceof LongLongType)
or ((len="ll" or len="L") and base instanceof LongLongType)
or (len="q" and base instanceof LongLongType)
)
and base.isSigned() and base = result.getBaseType()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
| printf1.h:44:18:44:20 | ull | This argument should be of type 'int' but is of type 'unsigned long long' |
| printf1.h:45:18:45:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:46:18:46:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:47:19:47:21 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:113:17:113:17 | d | This argument should be of type 'long double' but is of type 'double' |
| printf1.h:114:18:114:18 | d | This argument should be of type 'long double' but is of type 'double' |
| real_world.h:61:21:61:22 | & ... | This argument should be of type 'int *' but is of type 'short *' |
| real_world.h:62:22:62:23 | & ... | This argument should be of type 'short *' but is of type 'int *' |
| real_world.h:63:22:63:24 | & ... | This argument should be of type 'short *' but is of type 'unsigned int *' |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ void f(char *s, int i, unsigned char *us, const char *cs, signed char *ss, char
printf("%d", ull); // not ok (unsigned long long -> int)
printf("%u", ull); // not ok (unsigned long long -> unsigned int)
printf("%x", ull); // not ok (unsigned long long -> unsigned int)
printf("%Lx", ull); // not ok (unsigned long long -> unsigned int)
printf("%Lx", ull); // ok
printf("%llx", ull); // ok
}

Expand Down Expand Up @@ -101,3 +101,36 @@ void fun1(unsigned char* a, unsigned char* b) {
printf("%td\n", pdt); // GOOD
printf("%td\n", a-b); // GOOD
}

void extensions()
{
{
long double ld;
double d;

printf("%Lg", ld); // GOOD
printf("%llg", ld); // GOOD (nonstandard equivalent to %Lg)
printf("%Lg", d); // BAD (should be %g)
printf("%llg", d); // BAD (should be %g)
}

{
long long int lli;
long int li;

printf("%lld", lli); // GOOD
printf("%Ld", lli); // GOOD (nonstandard equivalent to %lld)
printf("%Ld", li); // BAD (should be %ld) [NOT DETECTED]
printf("%lld", li); // BAD (should be %ld) [NOT DETECTED]
}

{
unsigned long long int ulli;
unsigned long int uli;

printf("%llu", ulli); // GOOD
printf("%Lu", ulli); // GOOD (nonstandard equivalent to %llu)
printf("%Lu", uli); // BAD (should be %lu) [NOT DETECTED]
printf("%llu", uli); // BAD (should be %lu) [NOT DETECTED]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
| printf1.h:44:18:44:20 | ull | This argument should be of type 'int' but is of type 'unsigned long long' |
| printf1.h:45:18:45:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:46:18:46:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:47:19:47:21 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:126:18:126:19 | wc | This argument should be of type 'char *' but is of type 'wchar_t *' |
| printf1.h:127:18:127:18 | c | This argument should be of type 'wchar_t *' but is of type 'char *' |
| real_world.h:61:21:61:22 | & ... | This argument should be of type 'int *' but is of type 'short *' |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ void f(char *s, int i, unsigned char *us, const char *cs, signed char *ss, char
printf("%d", ull); // not ok (unsigned long long -> int)
printf("%u", ull); // not ok (unsigned long long -> unsigned int)
printf("%x", ull); // not ok (unsigned long long -> unsigned int)
printf("%Lx", ull); // not ok (unsigned long long -> unsigned int)
printf("%Lx", ull); // ok
printf("%llx", ull); // ok
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
| printf1.h:44:18:44:20 | ull | This argument should be of type 'int' but is of type 'unsigned long long' |
| printf1.h:45:18:45:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:46:18:46:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:47:19:47:21 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:71:19:71:20 | st | This argument should be of type 'ssize_t' but is of type 'unsigned long long' |
| printf1.h:72:19:72:20 | ST | This argument should be of type 'ssize_t' but is of type 'unsigned long long' |
| printf1.h:73:19:73:22 | c_st | This argument should be of type 'ssize_t' but is of type 'unsigned long long' |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ void f(char *s, int i, unsigned char *us, const char *cs, signed char *ss, char
printf("%d", ull); // not ok (unsigned long long -> int)
printf("%u", ull); // not ok (unsigned long long -> unsigned int)
printf("%x", ull); // not ok (unsigned long long -> unsigned int)
printf("%Lx", ull); // not ok (unsigned long long -> unsigned int)
printf("%Lx", ull); // ok
printf("%llx", ull); // ok
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
| printf1.h:44:18:44:20 | ull | This argument should be of type 'int' but is of type 'unsigned long long' |
| printf1.h:45:18:45:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:46:18:46:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:47:19:47:21 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
| printf1.h:71:19:71:20 | st | This argument should be of type 'ssize_t' but is of type 'unsigned long long' |
| printf1.h:72:19:72:20 | ST | This argument should be of type 'ssize_t' but is of type 'unsigned long long' |
| printf1.h:73:19:73:22 | c_st | This argument should be of type 'ssize_t' but is of type 'unsigned long long' |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ void f(char *s, int i, unsigned char *us, const char *cs, signed char *ss, char
printf("%d", ull); // not ok (unsigned long long -> int)
printf("%u", ull); // not ok (unsigned long long -> unsigned int)
printf("%x", ull); // not ok (unsigned long long -> unsigned int)
printf("%Lx", ull); // not ok (unsigned long long -> unsigned int)
printf("%Lx", ull); // ok
printf("%llx", ull); // ok
}

Expand Down