diff --git a/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql b/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql index 4f6c139b74be..2172b3dc3e55 100644 --- a/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql +++ b/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql @@ -25,8 +25,7 @@ private predicate formattingFunctionCallExpectedType(FormattingFunctionCall ffc, ffc.getTarget() = f and f.getFormatParameterIndex() = i and ffc.getArgument(i) = fl and - fl.getConversionType(pos) = expected and - count(fl.getConversionType(pos)) = 1 + fl.getConversionType(pos) = expected ) } @@ -143,7 +142,10 @@ from FormattingFunctionCall ffc, int n, Expr arg, Type expected, Type actual where ( ( formatArgType(ffc, n, expected, arg, actual) and - not trivialConversion(expected.getUnspecifiedType(), actual.getUnspecifiedType()) + not exists(Type anyExpected | + formatArgType(ffc, n, anyExpected, arg, actual) and + trivialConversion(anyExpected.getUnspecifiedType(), actual.getUnspecifiedType()) + ) ) or ( diff --git a/cpp/ql/src/semmle/code/cpp/commons/Printf.qll b/cpp/ql/src/semmle/code/cpp/commons/Printf.qll index 5e8f81a46114..96c3c46646fb 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Printf.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Printf.qll @@ -578,7 +578,7 @@ class FormatLiteral extends Literal { or ((len="z" or len="Z") and (result = this.getSize_t() or result = this.getSsize_t())) or (len="t" and result = this.getPtrdiff_t()) - or (len="I" and result instanceof IntType) + or (len="I" and (result = this.getSize_t() or result = this.getPtrdiff_t())) or (len="I32" and exists(MicrosoftInt32Type t | t.getUnsigned() = result.(IntegralType).getUnsigned() )) @@ -604,7 +604,7 @@ class FormatLiteral extends Literal { or ((len="z" or len="Z") and (result = this.getSize_t() or result = this.getSsize_t())) or (len="t" and result = this.getPtrdiff_t()) - or (len="I" and result instanceof IntType) + or (len="I" and (result = this.getSize_t() or result = this.getPtrdiff_t())) or (len="I32" and exists(MicrosoftInt32Type t | t.getUnsigned() = result.(IntegralType).getUnsigned() )) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_byte_wprintf/WrongTypeFormatArguments.expected b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_byte_wprintf/WrongTypeFormatArguments.expected index cfd9f690c38d..41f7c9683936 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_byte_wprintf/WrongTypeFormatArguments.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_byte_wprintf/WrongTypeFormatArguments.expected @@ -1,5 +1,7 @@ | tests.cpp:18:15:18:22 | Hello | This argument should be of type 'char *' but is of type 'char16_t *' | | tests.cpp:19:15:19:22 | Hello | This argument should be of type 'char *' but is of type 'wchar_t *' | +| tests.cpp:21:15:21:21 | Hello | This argument should be of type 'char16_t *' but is of type 'char *' | +| tests.cpp:21:15:21:21 | Hello | This argument should be of type 'wchar_t *' but is of type 'char *' | | tests.cpp:26:17:26:24 | Hello | This argument should be of type 'char *' but is of type 'char16_t *' | | tests.cpp:27:17:27:24 | Hello | This argument should be of type 'char *' but is of type 'wchar_t *' | | tests.cpp:29:17:29:23 | Hello | This argument should be of type 'wchar_t *' but is of type 'char *' | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_byte_wprintf/tests.cpp b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_byte_wprintf/tests.cpp index b1d2b5b1f035..cd802e2b501f 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_byte_wprintf/tests.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_byte_wprintf/tests.cpp @@ -18,7 +18,7 @@ void tests() { printf("%s", u"Hello"); // BAD: expecting char printf("%s", L"Hello"); // BAD: expecting char - printf("%S", "Hello"); // BAD: expecting wchar_t or char16_t [NOT DETECTED] + printf("%S", "Hello"); // BAD: expecting wchar_t or char16_t printf("%S", u"Hello"); // GOOD printf("%S", L"Hello"); // GOOD diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_word_size/WrongTypeFormatArguments.expected b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_word_size/WrongTypeFormatArguments.expected index f3cddba8012b..225d725b628b 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_word_size/WrongTypeFormatArguments.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_word_size/WrongTypeFormatArguments.expected @@ -1,2 +1,4 @@ | tests_32.cpp:14:16:14:23 | void_ptr | This argument should be of type 'long' but is of type 'void *' | +| tests_32.cpp:15:15:15:15 | l | This argument should be of type 'void *' but is of type 'long' | | tests_64.cpp:14:16:14:23 | void_ptr | This argument should be of type 'long' but is of type 'void *' | +| tests_64.cpp:15:15:15:15 | l | This argument should be of type 'void *' but is of type 'long' | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_word_size/tests_32.cpp b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_word_size/tests_32.cpp index 94aa803c6402..3c9b802a7a74 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_word_size/tests_32.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_word_size/tests_32.cpp @@ -12,6 +12,6 @@ void test_32() printf("%li", l); // GOOD printf("%li", void_ptr); // BAD - printf("%p", l); // BAD [NOT DETECTED] + printf("%p", l); // BAD printf("%p", void_ptr); // GOOD } diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_word_size/tests_64.cpp b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_word_size/tests_64.cpp index a9eda51c5c70..6b38c4e0245c 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_word_size/tests_64.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_word_size/tests_64.cpp @@ -12,6 +12,6 @@ void test_64() printf("%li", l); // GOOD printf("%li", void_ptr); // BAD - printf("%p", l); // BAD [NOT DETECTED] + printf("%p", l); // BAD printf("%p", void_ptr); // GOOD } diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/WrongTypeFormatArguments.expected b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/WrongTypeFormatArguments.expected index 648fda9c0cc2..c609cad22e9c 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/WrongTypeFormatArguments.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/WrongTypeFormatArguments.expected @@ -1,6 +1,7 @@ | format.h:16:59:16:61 | str | This argument should be of type 'int' but is of type 'char *' | | format.h:16:64:16:64 | i | This argument should be of type 'double' but is of type 'int' | | format.h:16:67:16:67 | d | This argument should be of type 'char *' but is of type 'double' | +| linux_c.c:11:15:11:18 | str3 | This argument should be of type 'char *' but is of type 'short *' | | pri_macros.h:15:35:15:40 | my_u64 | This argument should be of type 'unsigned int' but is of type 'unsigned long long' | | printf1.h:12:27:12:27 | i | This argument should be of type 'double' but is of type 'int' | | printf1.h:18:18:18:18 | i | This argument should be of type 'void *' but is of type 'int' | @@ -12,6 +13,8 @@ | printf1.h:46:18:46:20 | 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' | +| printf1.h:147:19:147:19 | i | This argument should be of type 'long long' but is of type 'int' | +| printf1.h:148:19:148:20 | ui | This argument should be of type 'unsigned long long' but is of type 'unsigned int' | | 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 *' | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/linux_c.c b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/linux_c.c new file mode 100644 index 000000000000..bc6468c593b5 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/linux_c.c @@ -0,0 +1,12 @@ +/** standard printf functions */ + +int printf(const char *format, ...); + +/** test program */ + +void restrict_cases(char * restrict str1, const char * restrict str2, short * restrict str3) +{ + printf("%s", str1); // GOOD + printf("%s", str2); // GOOD + printf("%s", str3); // BAD +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/options b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/options index 6591cabccf2b..fcea28bbb584 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/options +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/options @@ -1 +1 @@ -semmle-extractor-options: --edg --signed_chars +semmle-extractor-options: --clang --edg --signed_chars diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/printf1.h b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/printf1.h index 387811f0d557..ab9a9e186352 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/printf1.h +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/printf1.h @@ -134,3 +134,20 @@ void extensions() printf("%llu", uli); // BAD (should be %lu) [NOT DETECTED] } } + +void fun4() +{ + int i; + unsigned int ui; + long l; + unsigned long ul; + long long ll; + unsigned long long ull; + + printf("%qi\n", i); // BAD + printf("%qu\n", ui); // BAD + printf("%qi\n", l); // GOOD + printf("%qu\n", ul); // GOOD + printf("%qi\n", ll); // GOOD + printf("%qu\n", ull); // GOOD +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_unsigned_chars/WrongTypeFormatArguments.expected b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_unsigned_chars/WrongTypeFormatArguments.expected index a55c16faf904..f3feb82e6956 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_unsigned_chars/WrongTypeFormatArguments.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_unsigned_chars/WrongTypeFormatArguments.expected @@ -10,8 +10,11 @@ | 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: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 *' | +| printf1.h:130:18:130:18 | 0 | This argument should be of type 'void *' but is of type 'int' | +| printf1.h:154:18:154:19 | wc | This argument should be of type 'char *' but is of type 'wchar_t *' | +| printf1.h:155:18:155:18 | c | This argument should be of type 'wchar_t *' but is of type 'char *' | +| printf1.h:168:19:168:19 | i | This argument should be of type 'long long' but is of type 'int' | +| printf1.h:169:19:169:20 | ui | This argument should be of type 'unsigned long long' but is of type 'unsigned int' | | 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 *' | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_unsigned_chars/printf1.h b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_unsigned_chars/printf1.h index 0af5d8163f98..f919c62a6bc9 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_unsigned_chars/printf1.h +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_unsigned_chars/printf1.h @@ -102,6 +102,34 @@ void fun1(unsigned char* a, unsigned char* b) { printf("%td\n", a-b); // GOOD } +typedef wchar_t WCHAR_T; // WCHAR_T -> wchar_t -> int +typedef int MYCHAR; // MYCHAR -> int (notably not via the wchar_t typedef) + +void fun2() { + wchar_t *myString1; + WCHAR_T *myString2; + int *myString3; + MYCHAR *myString4; + + printf("%S", myString1); // GOOD + printf("%S", myString2); // GOOD + printf("%S", myString3); // GOOD + printf("%S", myString4); // GOOD +} + +typedef void *VOIDPTR; +typedef int (*FUNPTR)(int); + +void fun3(void *p1, VOIDPTR p2, FUNPTR p3, char *p4) +{ + printf("%p\n", p1); // GOOD + printf("%p\n", p2); // GOOD + printf("%p\n", p3); // GOOD + printf("%p\n", p4); // GOOD + printf("%p\n", p4 + 1); // GOOD + printf("%p\n", 0); // GOOD [FALSE POSITIVE] +} + typedef unsigned int wint_t; void test_chars(char c, wchar_t wc, wint_t wt) @@ -127,3 +155,20 @@ void test_ws(char *c, wchar_t *wc) wprintf(L"%S", c); // BAD wprintf(L"%S", wc); // GOOD } + +void fun4() +{ + int i; + unsigned int ui; + long l; + unsigned long ul; + long long ll; + unsigned long long ull; + + printf("%qi\n", i); // BAD + printf("%qu\n", ui); // BAD + printf("%qi\n", l); // GOOD + printf("%qu\n", ul); // GOOD + printf("%qi\n", ll); // GOOD + printf("%qu\n", ull); // GOOD +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft/WrongTypeFormatArguments.expected b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft/WrongTypeFormatArguments.expected index 5afaa3bddbe0..df9773eda7d9 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft/WrongTypeFormatArguments.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft/WrongTypeFormatArguments.expected @@ -16,8 +16,21 @@ | printf1.h:74:19:74:22 | C_ST | This argument should be of type 'ssize_t' but is of type 'unsigned long long' | | printf1.h:75:19:75:28 | sizeof() | This argument should be of type 'ssize_t' but is of type 'unsigned long long' | | printf1.h:84:23:84:35 | ... - ... | This argument should be of type 'ssize_t' but is of type 'long long' | -| printf1.h:125:18:125:18 | c | This argument should be of type '__wchar_t *' but is of type 'char *' | -| printf1.h:128:18:128:19 | wc | This argument should be of type 'char *' but is of type '__wchar_t *' | +| printf1.h:116:16:116:24 | myString3 | This argument should be of type '__wchar_t *' but is of type 'int *' | +| printf1.h:117:16:117:24 | myString4 | This argument should be of type '__wchar_t *' but is of type 'int *' | +| printf1.h:130:18:130:18 | 0 | This argument should be of type 'void *' but is of type 'int' | +| printf1.h:153:18:153:18 | c | This argument should be of type '__wchar_t *' but is of type 'char *' | +| printf1.h:156:18:156:19 | wc | This argument should be of type 'char *' but is of type '__wchar_t *' | +| printf1.h:181:21:181:22 | ll | This argument should be of type 'int' but is of type 'long long' | +| printf1.h:182:21:182:23 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' | +| printf1.h:185:21:185:23 | i64 | This argument should be of type 'int' but is of type 'long long' | +| printf1.h:186:21:186:23 | u64 | This argument should be of type 'unsigned int' but is of type 'unsigned long long' | +| printf1.h:188:21:188:21 | i | This argument should be of type 'long long' but is of type 'int' | +| printf1.h:189:21:189:22 | ui | This argument should be of type 'unsigned long long' but is of type 'unsigned int' | +| printf1.h:190:21:190:21 | l | This argument should be of type 'long long' but is of type 'long' | +| printf1.h:191:21:191:22 | ul | This argument should be of type 'unsigned long long' but is of type 'unsigned long' | +| printf1.h:194:21:194:23 | i32 | This argument should be of type 'long long' but is of type 'int' | +| printf1.h:195:21:195:23 | u32 | This argument should be of type 'unsigned long long' but is of type 'unsigned int' | | 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 *' | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft/printf1.h b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft/printf1.h index f77e0ac87fb0..962dc44b1caa 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft/printf1.h +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft/printf1.h @@ -102,6 +102,34 @@ void fun1(unsigned char* a, unsigned char* b) { printf("%td\n", a-b); // GOOD } +typedef wchar_t WCHAR_T; // WCHAR_T -> wchar_t +typedef int MYCHAR; // MYCHAR -> int + +void fun2() { + wchar_t *myString1; + WCHAR_T *myString2; + int *myString3; + MYCHAR *myString4; + + printf("%S", myString1); // GOOD + printf("%S", myString2); // GOOD + printf("%S", myString3); // BAD + printf("%S", myString4); // BAD +} + +typedef void *VOIDPTR; +typedef int (*FUNPTR)(int); + +void fun3(void *p1, VOIDPTR p2, FUNPTR p3, char *p4) +{ + printf("%p\n", p1); // GOOD + printf("%p\n", p2); // GOOD + printf("%p\n", p3); // GOOD + printf("%p\n", p4); // GOOD + printf("%p\n", p4 + 1); // GOOD + printf("%p\n", 0); // GOOD [FALSE POSITIVE] +} + typedef unsigned int wint_t; void test_chars(char c, wchar_t wc, wint_t wt) @@ -127,3 +155,44 @@ void test_ws(char *c, wchar_t *wc, wint_t *wt) wprintf(L"%S", c); // GOOD wprintf(L"%S", wc); // BAD } + +void fun4() +{ + ptrdiff_t pdt; + size_t sz; + int i; + unsigned int ui; + long l; + unsigned long ul; + long long ll; + unsigned long long ull; + __int32 i32; + unsigned __int32 u32; + __int64 i64; + unsigned __int64 u64; + + printf("%Ii\n", pdt); // GOOD + printf("%Iu\n", sz); // GOOD + + printf("%I32i\n", i); // GOOD + printf("%I32u\n", ui); // GOOD + printf("%I32i\n", l); // GOOD + printf("%I32u\n", ul); // GOOD + printf("%I32i\n", ll); // BAD + printf("%I32u\n", ull); // BAD + printf("%I32i\n", i32); // GOOD + printf("%I32u\n", u32); // GOOD + printf("%I32i\n", i64); // BAD + printf("%I32u\n", u64); // BAD + + printf("%I64i\n", i); // BAD + printf("%I64u\n", ui); // BAD + printf("%I64i\n", l); // BAD + printf("%I64u\n", ul); // BAD + printf("%I64i\n", ll); // GOOD + printf("%I64u\n", ull); // GOOD + printf("%I64i\n", i32); // BAD + printf("%I64u\n", u32); // BAD + printf("%I64i\n", i64); // GOOD + printf("%I64u\n", u64); // GOOD +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/WrongTypeFormatArguments.expected b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/WrongTypeFormatArguments.expected index 75536814cade..29435cab2c18 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/WrongTypeFormatArguments.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/WrongTypeFormatArguments.expected @@ -17,8 +17,19 @@ | printf1.h:75:19:75:28 | sizeof() | This argument should be of type 'ssize_t' but is of type 'unsigned long long' | | printf1.h:84:23:84:35 | ... - ... | This argument should be of type 'ssize_t' but is of type 'long long' | | printf1.h:130:18:130:18 | 0 | This argument should be of type 'void *' but is of type 'int' | +| printf1.h:155:21:155:22 | ll | This argument should be of type 'int' but is of type 'long long' | +| printf1.h:156:21:156:23 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' | +| printf1.h:159:21:159:23 | i64 | This argument should be of type 'int' but is of type 'long long' | +| printf1.h:160:21:160:23 | u64 | This argument should be of type 'unsigned int' but is of type 'unsigned long long' | +| printf1.h:162:21:162:21 | i | This argument should be of type 'long long' but is of type 'int' | +| printf1.h:163:21:163:22 | ui | This argument should be of type 'unsigned long long' but is of type 'unsigned int' | +| printf1.h:164:21:164:21 | l | This argument should be of type 'long long' but is of type 'long' | +| printf1.h:165:21:165:22 | ul | This argument should be of type 'unsigned long long' but is of type 'unsigned long' | +| printf1.h:168:21:168:23 | i32 | This argument should be of type 'long long' but is of type 'int' | +| printf1.h:169:21:169:23 | u32 | This argument should be of type 'unsigned long long' but is of type 'unsigned int' | | 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 *' | | real_world.h:64:22:64:24 | & ... | This argument should be of type 'short *' but is of type 'signed int *' | | wide_string.h:25:18:25:20 | c | This argument should be of type 'char' but is of type 'char *' | +| wide_string.h:29:19:29:22 | c | This argument should be of type 'wchar_t' but is of type 'unsigned short *' | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/printf1.h b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/printf1.h index ebff460c421f..223ffc6a2128 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/printf1.h +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/printf1.h @@ -129,3 +129,44 @@ void fun3(void *p1, VOIDPTR p2, FUNPTR p3, char *p4) printf("%p\n", p4 + 1); // GOOD printf("%p\n", 0); // GOOD [FALSE POSITIVE] } + +void fun4() +{ + ptrdiff_t pdt; + size_t sz; + int i; + unsigned int ui; + long l; + unsigned long ul; + long long ll; + unsigned long long ull; + __int32 i32; + unsigned __int32 u32; + __int64 i64; + unsigned __int64 u64; + + printf("%Ii\n", pdt); // GOOD + printf("%Iu\n", sz); // GOOD + + printf("%I32i\n", i); // GOOD + printf("%I32u\n", ui); // GOOD + printf("%I32i\n", l); // GOOD + printf("%I32u\n", ul); // GOOD + printf("%I32i\n", ll); // BAD + printf("%I32u\n", ull); // BAD + printf("%I32i\n", i32); // GOOD + printf("%I32u\n", u32); // GOOD + printf("%I32i\n", i64); // BAD + printf("%I32u\n", u64); // BAD + + printf("%I64i\n", i); // BAD + printf("%I64u\n", ui); // BAD + printf("%I64i\n", l); // BAD + printf("%I64u\n", ul); // BAD + printf("%I64i\n", ll); // GOOD + printf("%I64u\n", ull); // GOOD + printf("%I64i\n", i32); // BAD + printf("%I64u\n", u32); // BAD + printf("%I64i\n", i64); // GOOD + printf("%I64u\n", u64); // GOOD +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/wide_string.h b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/wide_string.h index 73bdee5b8b11..672329b62706 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/wide_string.h +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/wide_string.h @@ -26,5 +26,5 @@ void test_wchar4(char c, const char cc, wchar_t wc, const wchar_t wcc) { printf("%wc", wc); // GOOD printf("%wc", wcc); // GOOD printf("%wc", L'c'); // GOOD - printf("%wc", L"c"); // BAD [NOT DETECTED] + printf("%wc", L"c"); // BAD }