From f64743e91d849f7aea15a5dd0b98d36fc21e2ae6 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 4 Jul 2024 16:19:32 +0100 Subject: [PATCH 01/12] C++: Fix mistake in example for cpp/incorrect-allocation-error-handling. --- .../Security/CWE/CWE-570/IncorrectAllocationErrorHandling.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.cpp b/cpp/ql/src/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.cpp index 055aadcedb6..446cb14befa 100644 --- a/cpp/ql/src/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.cpp +++ b/cpp/ql/src/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.cpp @@ -34,7 +34,7 @@ void good1(std::size_t length) noexcept { // GOOD: the allocation failure is handled appropriately. void good2(std::size_t length) noexcept { - int* dest = new int[length]; + int* dest = new(std::nothrow) int[length]; if(!dest) { return; } From 4de43e1bfa0e8b044cdddd771f9ba0f2c85c7e50 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 4 Jul 2024 17:07:10 +0100 Subject: [PATCH 02/12] C++: Add the examples to the test. --- .../IncorrectAllocationErrorHandling.expected | 1 + .../query-tests/Security/CWE/CWE-570/test.cpp | 51 +++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.expected index 67f1bee2f54..1d48edd7cea 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.expected @@ -16,3 +16,4 @@ | test.cpp:151:9:151:24 | new | This allocation cannot throw. $@ is unnecessary. | test.cpp:152:15:152:18 | { ... } | This catch block | | test.cpp:199:15:199:35 | new | This allocation cannot throw. $@ is unnecessary. | test.cpp:201:16:201:19 | { ... } | This catch block | | test.cpp:212:14:212:34 | new | This allocation cannot throw. $@ is unnecessary. | test.cpp:213:34:213:36 | { ... } | This catch block | +| test.cpp:246:17:246:31 | new[] | This allocation cannot return null. $@ is unnecessary. | test.cpp:247:8:247:12 | ! ... | This check | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-570/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-570/test.cpp index 046acab20d4..cedef98a5d8 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-570/test.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-570/test.cpp @@ -233,3 +233,54 @@ void test_operator_new_without_exception_spec() { int* p = new(42, std::nothrow) int; // GOOD if(p == nullptr) {} } + +namespace std { + void *memset(void *s, int c, size_t n); +} + +// from the qhelp: +namespace qhelp { + // BAD: the allocation will throw an unhandled exception + // instead of returning a null pointer. + void bad1(std::size_t length) noexcept { + int* dest = new int[length]; + if(!dest) { + return; + } + std::memset(dest, 0, length); + // ... + } + + // BAD: the allocation won't throw an exception, but + // instead return a null pointer. [NOT DETECTED] + void bad2(std::size_t length) noexcept { + try { + int* dest = new(std::nothrow) int[length]; + std::memset(dest, 0, length); + // ... + } catch(std::bad_alloc&) { + // ... + } + } + + // GOOD: the allocation failure is handled appropriately. + void good1(std::size_t length) noexcept { + try { + int* dest = new int[length]; + std::memset(dest, 0, length); + // ... + } catch(std::bad_alloc&) { + // ... + } + } + + // GOOD: the allocation failure is handled appropriately. + void good2(std::size_t length) noexcept { + int* dest = new(std::nothrow) int[length]; + if(!dest) { + return; + } + std::memset(dest, 0, length); + // ... + } +} From 7abece46c741cfcb6b2f85e9fa82d9bfa793def2 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 4 Jul 2024 16:33:38 +0100 Subject: [PATCH 03/12] C++: Add a 'good' example for cpp/unsigned-difference-expression-compared-zero. --- .../CWE-191/UnsignedDifferenceExpressionComparedZero.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.c b/cpp/ql/src/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.c index d2f2b76fddc..c19afc017c3 100644 --- a/cpp/ql/src/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.c +++ b/cpp/ql/src/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.c @@ -1,5 +1,10 @@ unsigned limit = get_limit(); unsigned total = 0; -while (limit - total > 0) { // wrong: if `total` is greater than `limit` this will underflow and continue executing the loop. + +while (limit - total > 0) { // BAD: if `total` is greater than `limit` this will underflow and continue executing the loop. total += get_data(); -} \ No newline at end of file +} + +while (total < limit) { // GOOD: never underflows. + total += get_data(); +} From 1343e4c9aad2554f0db6d03b86047d5fe5c73947 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 4 Jul 2024 16:43:09 +0100 Subject: [PATCH 04/12] C++: Add another 'good' example for cpp/unsigned-difference-expression-compared-zero. --- .../CWE-191/UnsignedDifferenceExpressionComparedZero.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.c b/cpp/ql/src/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.c index c19afc017c3..38ecc79ef2d 100644 --- a/cpp/ql/src/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.c +++ b/cpp/ql/src/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.c @@ -1,10 +1,14 @@ -unsigned limit = get_limit(); -unsigned total = 0; +uint32_t limit = get_limit(); +uint32_t total = 0; while (limit - total > 0) { // BAD: if `total` is greater than `limit` this will underflow and continue executing the loop. total += get_data(); } -while (total < limit) { // GOOD: never underflows. +while (total < limit) { // GOOD: never underflows here because there is no arithmetic. + total += get_data(); +} + +while ((int64_t)limit - total > 0) { // GOOD: never underflows here because the result always fits in an `int64_t`. total += get_data(); } From 5d898727c069a4d634be12dde8de6f3b8eac5fa4 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 4 Jul 2024 17:00:25 +0100 Subject: [PATCH 05/12] C++: Add the examples to the test. --- ...dDifferenceExpressionComparedZero.expected | 1 + .../test.cpp | 25 ++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero/UnsignedDifferenceExpressionComparedZero.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero/UnsignedDifferenceExpressionComparedZero.expected index 85938f15499..64631c12679 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero/UnsignedDifferenceExpressionComparedZero.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero/UnsignedDifferenceExpressionComparedZero.expected @@ -13,3 +13,4 @@ | test.cpp:266:10:266:24 | ... > ... | Unsigned subtraction can never be negative. | | test.cpp:276:11:276:19 | ... > ... | Unsigned subtraction can never be negative. | | test.cpp:288:10:288:18 | ... > ... | Unsigned subtraction can never be negative. | +| test.cpp:312:9:312:25 | ... > ... | Unsigned subtraction can never be negative. | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero/test.cpp index 1a6aaa618e5..430160165e6 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero/test.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero/test.cpp @@ -43,7 +43,7 @@ void test(unsigned x, unsigned y, bool unknown) { while(cond()) { if(unknown) { y--; } } - + if(x - y > 0) { } // GOOD x = y; @@ -298,3 +298,26 @@ int test18() { return (a - b > 0); // GOOD (as b = 0) } + +typedef unsigned int uint32_t; +typedef long long int64_t; +uint32_t get_limit(); +uint32_t get_data(); + +void test19() { + // from the doc: + uint32_t limit = get_limit(); + uint32_t total = 0; + + while (limit - total > 0) { // BAD: if `total` is greater than `limit` this will underflow and continue executing the loop. + total += get_data(); + } + + while (total < limit) { // GOOD: never underflows here because there is no arithmetic. + total += get_data(); + } + + while ((int64_t)limit - total > 0) { // GOOD: never underflows here because the result always fits in an `int64_t`. + total += get_data(); + } +} From 0288499801ae4864ab9a1561e882c0c6e5298697 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 4 Jul 2024 17:28:29 +0100 Subject: [PATCH 06/12] C++: Rephrase the alert message for cpp/wrong-type-format-argument to be less prescriptive. --- .../Format/WrongTypeFormatArguments.ql | 3 +- .../WrongTypeFormatArguments.expected | 24 ++-- .../WrongTypeFormatArguments.expected | 8 +- .../WrongTypeFormatArguments.expected | 124 +++++++++--------- .../WrongTypeFormatArguments.expected | 4 +- .../WrongTypeFormatArguments.expected | 40 +++--- .../WrongTypeFormatArguments.expected | 74 +++++------ .../WrongTypeFormatArguments.expected | 70 +++++----- 8 files changed, 173 insertions(+), 174 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql b/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql index 492315ad8b7..96ee311637b 100644 --- a/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql +++ b/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql @@ -172,5 +172,4 @@ where not arg.isFromUninstantiatedTemplate(_) and not actual.getUnspecifiedType() instanceof ErroneousType select arg, - "This argument should be of type '" + expected.getName() + "' but is of type '" + - actual.getUnspecifiedType().getName() + "'." + "This format specifier for type '" + expected.getName() + "' does not match the argument type '" + actual.getUnspecifiedType().getName() + "'." 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 8dfd55c4174..99810e0e55d 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,12 +1,12 @@ -| 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:30:17:30:24 | Hello | This argument should be of type 'wchar_t *' but is of type 'char16_t *'. | -| tests.cpp:35:36:35:43 | Hello | This argument should be of type 'char *' but is of type 'wchar_t *'. | -| tests.cpp:39:36:39:43 | Hello | This argument should be of type 'char16_t *' but is of type 'wchar_t *'. | -| tests.cpp:42:37:42:44 | Hello | This argument should be of type 'char *' but is of type 'char16_t *'. | -| tests.cpp:43:37:43:44 | Hello | This argument should be of type 'char *' but is of type 'wchar_t *'. | -| tests.cpp:45:37:45:43 | Hello | This argument should be of type 'char16_t *' but is of type 'char *'. | -| tests.cpp:47:37:47:44 | Hello | This argument should be of type 'char16_t *' but is of type 'wchar_t *'. | +| tests.cpp:18:15:18:22 | Hello | This format specifier for type 'char *' does not match the argument type 'char16_t *'. | +| tests.cpp:19:15:19:22 | Hello | This format specifier for type 'char *' does not match the argument type 'wchar_t *'. | +| tests.cpp:21:15:21:21 | Hello | This format specifier for type 'char16_t *' does not match the argument type 'char *'. | +| tests.cpp:21:15:21:21 | Hello | This format specifier for type 'wchar_t *' does not match the argument type 'char *'. | +| tests.cpp:26:17:26:24 | Hello | This format specifier for type 'char *' does not match the argument type 'char16_t *'. | +| tests.cpp:30:17:30:24 | Hello | This format specifier for type 'wchar_t *' does not match the argument type 'char16_t *'. | +| tests.cpp:35:36:35:43 | Hello | This format specifier for type 'char *' does not match the argument type 'wchar_t *'. | +| tests.cpp:39:36:39:43 | Hello | This format specifier for type 'char16_t *' does not match the argument type 'wchar_t *'. | +| tests.cpp:42:37:42:44 | Hello | This format specifier for type 'char *' does not match the argument type 'char16_t *'. | +| tests.cpp:43:37:43:44 | Hello | This format specifier for type 'char *' does not match the argument type 'wchar_t *'. | +| tests.cpp:45:37:45:43 | Hello | This format specifier for type 'char16_t *' does not match the argument type 'char *'. | +| tests.cpp:47:37:47:44 | Hello | This format specifier for type 'char16_t *' does not match the argument type 'wchar_t *'. | 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 096e9c9cbae..907b0c1385b 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,4 +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'. | +| tests_32.cpp:14:16:14:23 | void_ptr | This format specifier for type 'long' does not match the argument type 'void *'. | +| tests_32.cpp:15:15:15:15 | l | This format specifier for type 'void *' does not match the argument type 'long'. | +| tests_64.cpp:14:16:14:23 | void_ptr | This format specifier for type 'long' does not match the argument type 'void *'. | +| tests_64.cpp:15:15:15:15 | l | This format specifier for type 'void *' does not match the argument type 'long'. | 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 8556ab875a4..f3963eff2b0 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,62 +1,62 @@ -| 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.cpp:15:24:15:41 | call to get_template_value | This argument should be of type 'int' but is of type 'long'. | -| 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'. | -| printf1.h:25:22:25:22 | i | This argument should be of type 'char *' but is of type 'int'. | -| printf1.h:27:19:27:20 | cs | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:38:18:38:30 | MYONETHOUSAND | This argument should be of type 'char *' but is of type 'int'. | -| 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: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'. | -| printf1.h:160:18:160:18 | i | This argument should be of type 'char *' but is of type 'int'. | -| printf1.h:161:21:161:21 | s | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:167:17:167:17 | i | This argument should be of type 'char *' but is of type 'int'. | -| printf1.h:168:18:168:18 | i | This argument should be of type 'char *' but is of type 'int'. | -| printf1.h:169:19:169:19 | i | This argument should be of type 'char *' but is of type 'int'. | -| printf1.h:174:17:174:17 | s | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:175:18:175:18 | s | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:176:19:176:19 | s | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:180:17:180:17 | s | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:181:20:181:20 | i | This argument should be of type 'char *' but is of type 'int'. | -| printf1.h:183:18:183:18 | s | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:184:21:184:21 | i | This argument should be of type 'char *' but is of type 'int'. | -| printf1.h:186:19:186:19 | s | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:187:22:187:22 | i | This argument should be of type 'char *' but is of type 'int'. | -| printf1.h:189:19:189:19 | s | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:190:22:190:22 | i | This argument should be of type 'char *' but is of type 'int'. | -| printf1.h:192:19:192:19 | s | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:193:22:193:22 | s | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:194:25:194:25 | i | This argument should be of type 'char *' but is of type 'int'. | -| printf1.h:198:24:198:24 | s | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:199:21:199:21 | i | This argument should be of type 'char *' but is of type 'int'. | -| printf1.h:202:26:202:26 | s | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:203:23:203:23 | i | This argument should be of type 'char *' but is of type 'int'. | -| printf1.h:206:25:206:25 | s | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:207:22:207:22 | i | This argument should be of type 'char *' but is of type 'int'. | -| printf1.h:210:26:210:26 | s | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:211:23:211:23 | i | This argument should be of type 'char *' but is of type 'int'. | -| printf1.h:214:28:214:28 | s | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:215:28:215:28 | s | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:216:25:216:25 | i | This argument should be of type 'char *' but is of type 'int'. | -| printf1.h:221:18:221:18 | s | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:222:20:222:20 | s | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:225:23:225:23 | i | This argument should be of type 'char *' but is of type 'int'. | -| printf1.h:228:24:228:24 | i | This argument should be of type 'char *' but is of type 'int'. | -| printf1.h:231:25:231:25 | i | This argument should be of type 'char *' but is of type 'int'. | -| printf1.h:234:25:234:25 | i | This argument should be of type 'char *' but is of type 'int'. | -| printf1.h:235:22:235:22 | s | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:276:32:276:32 | s | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:278:17:278:17 | s | This argument should be of type 'int' but is of type 'char *'. | -| 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 *'. | +| format.h:16:59:16:61 | str | This format specifier for type 'int' does not match the argument type 'char *'. | +| format.h:16:64:16:64 | i | This format specifier for type 'double' does not match the argument type 'int'. | +| format.h:16:67:16:67 | d | This format specifier for type 'char *' does not match the argument type 'double'. | +| linux.cpp:15:24:15:41 | call to get_template_value | This format specifier for type 'int' does not match the argument type 'long'. | +| linux_c.c:11:15:11:18 | str3 | This format specifier for type 'char *' does not match the argument type 'short *'. | +| pri_macros.h:15:35:15:40 | my_u64 | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. | +| printf1.h:12:27:12:27 | i | This format specifier for type 'double' does not match the argument type 'int'. | +| printf1.h:18:18:18:18 | i | This format specifier for type 'void *' does not match the argument type 'int'. | +| printf1.h:25:22:25:22 | i | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:27:19:27:20 | cs | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:38:18:38:30 | MYONETHOUSAND | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:44:18:44:20 | ull | This format specifier for type 'int' does not match the argument type 'unsigned long long'. | +| printf1.h:45:18:45:20 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. | +| printf1.h:46:18:46:20 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. | +| printf1.h:113:17:113:17 | d | This format specifier for type 'long double' does not match the argument type 'double'. | +| printf1.h:114:18:114:18 | d | This format specifier for type 'long double' does not match the argument type 'double'. | +| printf1.h:147:19:147:19 | i | This format specifier for type 'long long' does not match the argument type 'int'. | +| printf1.h:148:19:148:20 | ui | This format specifier for type 'unsigned long long' does not match the argument type 'unsigned int'. | +| printf1.h:160:18:160:18 | i | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:161:21:161:21 | s | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:167:17:167:17 | i | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:168:18:168:18 | i | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:169:19:169:19 | i | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:174:17:174:17 | s | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:175:18:175:18 | s | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:176:19:176:19 | s | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:180:17:180:17 | s | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:181:20:181:20 | i | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:183:18:183:18 | s | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:184:21:184:21 | i | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:186:19:186:19 | s | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:187:22:187:22 | i | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:189:19:189:19 | s | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:190:22:190:22 | i | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:192:19:192:19 | s | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:193:22:193:22 | s | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:194:25:194:25 | i | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:198:24:198:24 | s | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:199:21:199:21 | i | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:202:26:202:26 | s | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:203:23:203:23 | i | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:206:25:206:25 | s | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:207:22:207:22 | i | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:210:26:210:26 | s | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:211:23:211:23 | i | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:214:28:214:28 | s | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:215:28:215:28 | s | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:216:25:216:25 | i | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:221:18:221:18 | s | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:222:20:222:20 | s | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:225:23:225:23 | i | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:228:24:228:24 | i | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:231:25:231:25 | i | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:234:25:234:25 | i | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:235:22:235:22 | s | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:276:32:276:32 | s | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:278:17:278:17 | s | This format specifier for type 'int' does not match the argument type 'char *'. | +| real_world.h:61:21:61:22 | & ... | This format specifier for type 'int *' does not match the argument type 'short *'. | +| real_world.h:62:22:62:23 | & ... | This format specifier for type 'short *' does not match the argument type 'int *'. | +| real_world.h:63:22:63:24 | & ... | This format specifier for type 'short *' does not match the argument type 'unsigned int *'. | +| real_world.h:64:22:64:24 | & ... | This format specifier for type 'short *' does not match the argument type 'signed int *'. | +| wide_string.h:25:18:25:20 | c | This format specifier for type 'char' does not match the argument type 'char *'. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_two_byte_wprintf/WrongTypeFormatArguments.expected b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_two_byte_wprintf/WrongTypeFormatArguments.expected index 1a1ff20bd27..0e62df1dd7f 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_two_byte_wprintf/WrongTypeFormatArguments.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_two_byte_wprintf/WrongTypeFormatArguments.expected @@ -1,2 +1,2 @@ -| printf.cpp:43:29:43:35 | test | This argument should be of type 'char *' but is of type 'char16_t *'. | -| printf.cpp:50:29:50:35 | test | This argument should be of type 'char16_t *' but is of type 'wchar_t *'. | +| printf.cpp:43:29:43:35 | test | This format specifier for type 'char *' does not match the argument type 'char16_t *'. | +| printf.cpp:50:29:50:35 | test | This format specifier for type 'char16_t *' does not match the argument type 'wchar_t *'. | 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 de24649beb8..45bf793082e 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 @@ -1,20 +1,20 @@ -| 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'. | -| 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'. | -| printf1.h:25:22:25:22 | i | This argument should be of type 'char *' but is of type 'int'. | -| printf1.h:27:19:27:20 | cs | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:38:18:38:30 | MYONETHOUSAND | This argument should be of type 'char *' but is of type 'int'. | -| 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:130:18:130:18 | 0 | This argument should be of type 'void *' but is of type 'int'. | -| 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 *'. | -| 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 *'. | +| format.h:16:59:16:61 | str | This format specifier for type 'int' does not match the argument type 'char *'. | +| format.h:16:64:16:64 | i | This format specifier for type 'double' does not match the argument type 'int'. | +| format.h:16:67:16:67 | d | This format specifier for type 'char *' does not match the argument type 'double'. | +| pri_macros.h:15:35:15:40 | my_u64 | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. | +| printf1.h:12:27:12:27 | i | This format specifier for type 'double' does not match the argument type 'int'. | +| printf1.h:18:18:18:18 | i | This format specifier for type 'void *' does not match the argument type 'int'. | +| printf1.h:25:22:25:22 | i | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:27:19:27:20 | cs | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:38:18:38:30 | MYONETHOUSAND | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:44:18:44:20 | ull | This format specifier for type 'int' does not match the argument type 'unsigned long long'. | +| printf1.h:45:18:45:20 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. | +| printf1.h:46:18:46:20 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. | +| printf1.h:130:18:130:18 | 0 | This format specifier for type 'void *' does not match the argument type 'int'. | +| printf1.h:168:19:168:19 | i | This format specifier for type 'long long' does not match the argument type 'int'. | +| printf1.h:169:19:169:20 | ui | This format specifier for type 'unsigned long long' does not match the argument type 'unsigned int'. | +| real_world.h:61:21:61:22 | & ... | This format specifier for type 'int *' does not match the argument type 'short *'. | +| real_world.h:62:22:62:23 | & ... | This format specifier for type 'short *' does not match the argument type 'int *'. | +| real_world.h:63:22:63:24 | & ... | This format specifier for type 'short *' does not match the argument type 'unsigned int *'. | +| real_world.h:64:22:64:24 | & ... | This format specifier for type 'short *' does not match the argument type 'signed int *'. | +| wide_string.h:25:18:25:20 | c | This format specifier for type 'char' does not match the argument type 'char *'. | 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 8e2cdb7845a..8a05434fde6 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 @@ -1,37 +1,37 @@ -| 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'. | -| 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'. | -| printf1.h:25:22:25:22 | i | This argument should be of type 'char *' but is of type 'int'. | -| printf1.h:27:19:27:20 | cs | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:38:18:38:30 | MYONETHOUSAND | This argument should be of type 'char *' but is of type 'int'. | -| 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: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'. | -| 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: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: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 *'. | -| 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 '__wchar_t *'. | +| format.h:16:59:16:61 | str | This format specifier for type 'int' does not match the argument type 'char *'. | +| format.h:16:64:16:64 | i | This format specifier for type 'double' does not match the argument type 'int'. | +| format.h:16:67:16:67 | d | This format specifier for type 'char *' does not match the argument type 'double'. | +| pri_macros.h:15:35:15:40 | my_u64 | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. | +| printf1.h:12:27:12:27 | i | This format specifier for type 'double' does not match the argument type 'int'. | +| printf1.h:18:18:18:18 | i | This format specifier for type 'void *' does not match the argument type 'int'. | +| printf1.h:25:22:25:22 | i | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:27:19:27:20 | cs | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:38:18:38:30 | MYONETHOUSAND | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:44:18:44:20 | ull | This format specifier for type 'int' does not match the argument type 'unsigned long long'. | +| printf1.h:45:18:45:20 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. | +| printf1.h:46:18:46:20 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. | +| printf1.h:71:19:71:20 | st | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. | +| printf1.h:72:19:72:20 | ST | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. | +| printf1.h:73:19:73:22 | c_st | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. | +| printf1.h:74:19:74:22 | C_ST | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. | +| printf1.h:75:19:75:28 | sizeof() | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. | +| printf1.h:84:23:84:35 | ... - ... | This format specifier for type 'ssize_t' does not match the argument type 'long long'. | +| printf1.h:116:16:116:24 | myString3 | This format specifier for type '__wchar_t *' does not match the argument type 'int *'. | +| printf1.h:117:16:117:24 | myString4 | This format specifier for type '__wchar_t *' does not match the argument type 'int *'. | +| printf1.h:130:18:130:18 | 0 | This format specifier for type 'void *' does not match the argument type 'int'. | +| printf1.h:181:21:181:22 | ll | This format specifier for type 'int' does not match the argument type 'long long'. | +| printf1.h:182:21:182:23 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. | +| printf1.h:185:21:185:23 | i64 | This format specifier for type 'int' does not match the argument type 'long long'. | +| printf1.h:186:21:186:23 | u64 | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. | +| printf1.h:188:21:188:21 | i | This format specifier for type 'long long' does not match the argument type 'int'. | +| printf1.h:189:21:189:22 | ui | This format specifier for type 'unsigned long long' does not match the argument type 'unsigned int'. | +| printf1.h:190:21:190:21 | l | This format specifier for type 'long long' does not match the argument type 'long'. | +| printf1.h:191:21:191:22 | ul | This format specifier for type 'unsigned long long' does not match the argument type 'unsigned long'. | +| printf1.h:194:21:194:23 | i32 | This format specifier for type 'long long' does not match the argument type 'int'. | +| printf1.h:195:21:195:23 | u32 | This format specifier for type 'unsigned long long' does not match the argument type 'unsigned int'. | +| real_world.h:61:21:61:22 | & ... | This format specifier for type 'int *' does not match the argument type 'short *'. | +| real_world.h:62:22:62:23 | & ... | This format specifier for type 'short *' does not match the argument type 'int *'. | +| real_world.h:63:22:63:24 | & ... | This format specifier for type 'short *' does not match the argument type 'unsigned int *'. | +| real_world.h:64:22:64:24 | & ... | This format specifier for type 'short *' does not match the argument type 'signed int *'. | +| wide_string.h:25:18:25:20 | c | This format specifier for type 'char' does not match the argument type 'char *'. | +| wide_string.h:29:19:29:22 | c | This format specifier for type 'wchar_t' does not match the argument type '__wchar_t *'. | 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 933e2ec297b..f50708f9eb4 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 @@ -1,35 +1,35 @@ -| 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'. | -| 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'. | -| printf1.h:25:22:25:22 | i | This argument should be of type 'char *' but is of type 'int'. | -| printf1.h:27:19:27:20 | cs | This argument should be of type 'int' but is of type 'char *'. | -| printf1.h:38:18:38:30 | MYONETHOUSAND | This argument should be of type 'char *' but is of type 'int'. | -| 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: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'. | -| 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: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 *'. | +| format.h:16:59:16:61 | str | This format specifier for type 'int' does not match the argument type 'char *'. | +| format.h:16:64:16:64 | i | This format specifier for type 'double' does not match the argument type 'int'. | +| format.h:16:67:16:67 | d | This format specifier for type 'char *' does not match the argument type 'double'. | +| pri_macros.h:15:35:15:40 | my_u64 | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. | +| printf1.h:12:27:12:27 | i | This format specifier for type 'double' does not match the argument type 'int'. | +| printf1.h:18:18:18:18 | i | This format specifier for type 'void *' does not match the argument type 'int'. | +| printf1.h:25:22:25:22 | i | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:27:19:27:20 | cs | This format specifier for type 'int' does not match the argument type 'char *'. | +| printf1.h:38:18:38:30 | MYONETHOUSAND | This format specifier for type 'char *' does not match the argument type 'int'. | +| printf1.h:44:18:44:20 | ull | This format specifier for type 'int' does not match the argument type 'unsigned long long'. | +| printf1.h:45:18:45:20 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. | +| printf1.h:46:18:46:20 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. | +| printf1.h:71:19:71:20 | st | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. | +| printf1.h:72:19:72:20 | ST | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. | +| printf1.h:73:19:73:22 | c_st | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. | +| printf1.h:74:19:74:22 | C_ST | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. | +| printf1.h:75:19:75:28 | sizeof() | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. | +| printf1.h:84:23:84:35 | ... - ... | This format specifier for type 'ssize_t' does not match the argument type 'long long'. | +| printf1.h:130:18:130:18 | 0 | This format specifier for type 'void *' does not match the argument type 'int'. | +| printf1.h:155:21:155:22 | ll | This format specifier for type 'int' does not match the argument type 'long long'. | +| printf1.h:156:21:156:23 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. | +| printf1.h:159:21:159:23 | i64 | This format specifier for type 'int' does not match the argument type 'long long'. | +| printf1.h:160:21:160:23 | u64 | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. | +| printf1.h:162:21:162:21 | i | This format specifier for type 'long long' does not match the argument type 'int'. | +| printf1.h:163:21:163:22 | ui | This format specifier for type 'unsigned long long' does not match the argument type 'unsigned int'. | +| printf1.h:164:21:164:21 | l | This format specifier for type 'long long' does not match the argument type 'long'. | +| printf1.h:165:21:165:22 | ul | This format specifier for type 'unsigned long long' does not match the argument type 'unsigned long'. | +| printf1.h:168:21:168:23 | i32 | This format specifier for type 'long long' does not match the argument type 'int'. | +| printf1.h:169:21:169:23 | u32 | This format specifier for type 'unsigned long long' does not match the argument type 'unsigned int'. | +| real_world.h:61:21:61:22 | & ... | This format specifier for type 'int *' does not match the argument type 'short *'. | +| real_world.h:62:22:62:23 | & ... | This format specifier for type 'short *' does not match the argument type 'int *'. | +| real_world.h:63:22:63:24 | & ... | This format specifier for type 'short *' does not match the argument type 'unsigned int *'. | +| real_world.h:64:22:64:24 | & ... | This format specifier for type 'short *' does not match the argument type 'signed int *'. | +| wide_string.h:25:18:25:20 | c | This format specifier for type 'char' does not match the argument type 'char *'. | +| wide_string.h:29:19:29:22 | c | This format specifier for type 'wchar_t' does not match the argument type 'unsigned short *'. | From 3c70583aa24605e78f4559564093316560c190ee Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 8 Jul 2024 10:23:09 +0100 Subject: [PATCH 07/12] C++: Add close calls to examples for cpp/toctou-race-condition. --- .../Security/CWE/CWE-367/TOCTOUFilesystemRaceBad.c | 12 +++++++----- .../Security/CWE/CWE-367/TOCTOUFilesystemRaceGood.c | 12 +++++++----- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-367/TOCTOUFilesystemRaceBad.c b/cpp/ql/src/Security/CWE/CWE-367/TOCTOUFilesystemRaceBad.c index 03e8a82a38c..993364a54d4 100644 --- a/cpp/ql/src/Security/CWE/CWE-367/TOCTOUFilesystemRaceBad.c +++ b/cpp/ql/src/Security/CWE/CWE-367/TOCTOUFilesystemRaceBad.c @@ -1,15 +1,17 @@ char *file_name; FILE *f_ptr; - + /* Initialize file_name */ - + f_ptr = fopen(file_name, "w"); if (f_ptr == NULL) { /* Handle error */ } - + /* ... */ - + if (chmod(file_name, S_IRUSR) == -1) { /* Handle error */ -} \ No newline at end of file +} + +fclose(f_ptr); diff --git a/cpp/ql/src/Security/CWE/CWE-367/TOCTOUFilesystemRaceGood.c b/cpp/ql/src/Security/CWE/CWE-367/TOCTOUFilesystemRaceGood.c index bf14cffbd4d..4e5fb19a03f 100644 --- a/cpp/ql/src/Security/CWE/CWE-367/TOCTOUFilesystemRaceGood.c +++ b/cpp/ql/src/Security/CWE/CWE-367/TOCTOUFilesystemRaceGood.c @@ -1,8 +1,8 @@ char *file_name; int fd; - + /* Initialize file_name */ - + fd = open( file_name, O_WRONLY | O_CREAT | O_EXCL, @@ -11,9 +11,11 @@ fd = open( if (fd == -1) { /* Handle error */ } - + /* ... */ - + if (fchmod(fd, S_IRUSR) == -1) { /* Handle error */ -} \ No newline at end of file +} + +close(fd); From d52210d565b6e2600e55c0c6197ca026df15ef14 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 8 Jul 2024 10:59:09 +0100 Subject: [PATCH 08/12] C++: Improve the example for cpp/return-stack-allocated-memory. --- .../Memory Management/ReturnStackAllocatedMemory.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.cpp b/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.cpp index bf9822d5fd8..3fbebbc5953 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.cpp +++ b/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.cpp @@ -1,7 +1,5 @@ -Record* fixRecord(Record* r) { - Record myRecord = *r; - delete r; +Record *mkRecord(int value) { + Record myRecord(value); - myRecord.fix(); - return &myRecord; //returns reference to myRecord, which is a stack-allocated object -} \ No newline at end of file + return &myRecord; // BAD: return a pointer to `myRecord`, which is a stack-allocated object +} From 4f0d725acd188fff20de5874c7e3e64635619c79 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 8 Jul 2024 11:06:21 +0100 Subject: [PATCH 09/12] C++: Add a 'good' example as well. --- .../ReturnStackAllocatedMemory.cpp | 5 ----- .../ReturnStackAllocatedMemory.qhelp | 19 ++++++++++--------- .../ReturnStackAllocatedMemoryBad.cpp | 5 +++++ .../ReturnStackAllocatedMemoryGood.cpp | 5 +++++ 4 files changed, 20 insertions(+), 14 deletions(-) delete mode 100644 cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.cpp create mode 100644 cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemoryBad.cpp create mode 100644 cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemoryGood.cpp diff --git a/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.cpp b/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.cpp deleted file mode 100644 index 3fbebbc5953..00000000000 --- a/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.cpp +++ /dev/null @@ -1,5 +0,0 @@ -Record *mkRecord(int value) { - Record myRecord(value); - - return &myRecord; // BAD: return a pointer to `myRecord`, which is a stack-allocated object -} diff --git a/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.qhelp b/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.qhelp index 0c59a36199e..a5bc20ffe97 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.qhelp +++ b/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.qhelp @@ -5,22 +5,23 @@ -

This rule finds return statements that return pointers to an object allocated on the stack. -The lifetime of a stack allocated memory location only lasts until the function returns, and -the contents of that memory become undefined after that. Clearly, using a pointer to stack +

This rule finds return statements that return pointers to an object allocated on the stack. +The lifetime of a stack allocated memory location only lasts until the function returns, and +the contents of that memory become undefined after that. Clearly, using a pointer to stack memory after the function has already returned will have undefined results.

-

Use the functions of the malloc family to dynamically allocate memory on the heap for data that is used across function calls.

+

Use the functions of the malloc family, or new, to dynamically allocate memory on the heap for data that is used across function calls.

- - - - - + +

The following example allocates an object on the stack and returns a pointer to it. This is incorrect because the object is deallocated +when the function returns, and the pointer becomes invalid.

+ +

To fix this, allocate the object on the heap using new and return a pointer to the heap-allocated object.

+
diff --git a/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemoryBad.cpp b/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemoryBad.cpp new file mode 100644 index 00000000000..196410d840f --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemoryBad.cpp @@ -0,0 +1,5 @@ +Record *mkRecord(int value) { + Record myRecord(value); + + return &myRecord; // BAD: returns a pointer to `myRecord`, which is a stack-allocated object. +} diff --git a/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemoryGood.cpp b/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemoryGood.cpp new file mode 100644 index 00000000000..e888a7fbfe2 --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemoryGood.cpp @@ -0,0 +1,5 @@ +Record *mkRecord(int value) { + Record *myRecord = new Record(value); + + return myRecord; // GOOD: returns a pointer to a `myRecord`, which is a heap-allocated object. +} From 80af5b772537a5a9ae673a384235869935a47c3c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 8 Jul 2024 12:29:44 +0100 Subject: [PATCH 10/12] C++: Add a third example for cpp/world-writable-file-creation. --- cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.c | 7 +++++++ .../Security/CWE/CWE-732/DoNotCreateWorldWritable.qhelp | 5 +++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.c b/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.c index b015770ad80..506eb1d2ff1 100644 --- a/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.c +++ b/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.c @@ -9,3 +9,10 @@ void write_default_config_good() { int out = creat(OUTFILE, S_IWUSR | S_IRUSR); dprintf(out, DEFAULT_CONFIG); } + +void write_default_config_good_2() { + // GOOD - this allows only the current user to modify the file + int out = open(OUTFILE, O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR); + FILE *fd = fdopen(out, "w"); + fprintf(fd, DEFAULT_CONFIG); +} diff --git a/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.qhelp b/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.qhelp index 6ee95149041..58a5a55f509 100644 --- a/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.qhelp +++ b/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.qhelp @@ -29,10 +29,11 @@ so it is important that they cannot be controlled by an attacker.

-The first example creates the default configuration file with the usual "default" Unix permissions, 0666. This makes the +The first example creates the default configuration file with the usual "default" Unix permissions, 0666. This makes the file world-writable, so that an attacker could write in their own configuration that would be read by the program. The second example uses more restrictive permissions: a combination of the standard Unix constants S_IWUSR and S_IRUSR which means that -only the current user will have read and write access to the file. +only the current user will have read and write access to the file. The third example shows another way to create a file with more restrictive +permissions if a FILE * stream pointer is required rather than a file descriptor.

From 8818f63ca7b351feda880571d7223fd279566a61 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 8 Jul 2024 12:34:39 +0100 Subject: [PATCH 11/12] C++: Add some practical details to the examples. --- .../CWE/CWE-732/DoNotCreateWorldWritable.c | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.c b/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.c index 506eb1d2ff1..f4c544445c0 100644 --- a/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.c +++ b/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.c @@ -1,18 +1,38 @@ void write_default_config_bad() { // BAD - this is world-writable so any user can overwrite the config int out = creat(OUTFILE, 0666); - dprintf(out, DEFAULT_CONFIG); + if (out < 0) { + // handle error + } + + dprintf(out, "%s", DEFAULT_CONFIG); + close(out); } void write_default_config_good() { // GOOD - this allows only the current user to modify the file int out = creat(OUTFILE, S_IWUSR | S_IRUSR); - dprintf(out, DEFAULT_CONFIG); + if (out < 0) { + // handle error + } + + dprintf(out, "%s", DEFAULT_CONFIG); + close(out); } void write_default_config_good_2() { // GOOD - this allows only the current user to modify the file int out = open(OUTFILE, O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR); + if (out < 0) { + // handle error + } + FILE *fd = fdopen(out, "w"); - fprintf(fd, DEFAULT_CONFIG); + if (fd == NULL) { + close(out); + // handle error + } + + fprintf(fd, "%s", DEFAULT_CONFIG); + fclose(fd); } From 74384625f665b4a789a2e71e2e54c30fe9f6f82f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 10 Jul 2024 11:17:44 +0100 Subject: [PATCH 12/12] C++: Autoformat. --- cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql b/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql index 96ee311637b..e38bfbf562b 100644 --- a/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql +++ b/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql @@ -172,4 +172,5 @@ where not arg.isFromUninstantiatedTemplate(_) and not actual.getUnspecifiedType() instanceof ErroneousType select arg, - "This format specifier for type '" + expected.getName() + "' does not match the argument type '" + actual.getUnspecifiedType().getName() + "'." + "This format specifier for type '" + expected.getName() + "' does not match the argument type '" + + actual.getUnspecifiedType().getName() + "'."