diff --git a/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql b/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql index 33fe3a0b7a15..7f0a4833cb59 100644 --- a/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql +++ b/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql @@ -168,9 +168,11 @@ where formatOtherArgType(ffc, n, expected, arg, actual) and not actual.getUnspecifiedType().(IntegralType).getSize() = sizeof_IntType() ) and + // Exclude some cases where we're less confident the result is correct / clear / valuable not arg.isAffectedByMacro() and not arg.isFromUninstantiatedTemplate(_) and not actual.stripType() instanceof ErroneousType and + not arg.getType().stripType().(RoutineType).getReturnType() instanceof ErroneousType and not arg.(Call).mayBeFromImplicitlyDeclaredFunction() and // Make sure that the format function definition is consistent count(ffc.getTarget().getFormatParameterIndex()) = 1 diff --git a/cpp/ql/src/change-notes/2026-03-16-wrong-type-format-argument.md b/cpp/ql/src/change-notes/2026-03-16-wrong-type-format-argument.md new file mode 100644 index 000000000000..84aef7791fcf --- /dev/null +++ b/cpp/ql/src/change-notes/2026-03-16-wrong-type-format-argument.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Fixed an issue with the "Wrong type of arguments to formatting function" (`cpp/wrong-type-format-argument`) query causing false positive results in `build-mode: none` databases. diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Buildless/WrongTypeFormatArguments.expected b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Buildless/WrongTypeFormatArguments.expected index 745f2f790f79..8eefcc95a24f 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Buildless/WrongTypeFormatArguments.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Buildless/WrongTypeFormatArguments.expected @@ -1 +1,3 @@ +| second.cpp:26:18:26:39 | ... - ... | This format specifier for type 'int' does not match the argument type 'long'. | +| second.cpp:29:18:29:39 | ... - ... | This format specifier for type 'unsigned int' does not match the argument type 'long'. | | tests.c:7:18:7:18 | 1 | This format specifier for type 'char *' does not match the argument type 'int'. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Buildless/first.cpp b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Buildless/first.cpp new file mode 100644 index 000000000000..8973ace78c76 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Buildless/first.cpp @@ -0,0 +1,3 @@ + +// defines type size_t plausibly +typedef unsigned long size_t; diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Buildless/second.cpp b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Buildless/second.cpp new file mode 100644 index 000000000000..9ebbc4dd6e0a --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Buildless/second.cpp @@ -0,0 +1,30 @@ +// semmle-extractor-options: --expect_errors + +int printf(const char * format, ...); + +// defines type `myFunctionPointerType`, referencing `size_t` +typedef size_t (*myFunctionPointerType) (); + +void test_size_t() { + size_t s = 0; + + printf("%zd", s); // GOOD + printf("%zi", s); // GOOD + printf("%zu", s); // GOOD (we generally permit signedness changes) + printf("%zx", s); // GOOD (we generally permit signedness changes) + printf("%d", s); // BAD [NOT DETECTED] + printf("%ld", s); // BAD [NOT DETECTED] + printf("%lld", s); // BAD [NOT DETECTED] + printf("%u", s); // BAD [NOT DETECTED] + + char buffer[1024]; + + printf("%zd", &buffer[1023] - buffer); // GOOD + printf("%zi", &buffer[1023] - buffer); // GOOD + printf("%zu", &buffer[1023] - buffer); // GOOD + printf("%zx", &buffer[1023] - buffer); // GOOD + printf("%d", &buffer[1023] - buffer); // BAD + printf("%ld", &buffer[1023] - buffer); // BAD [NOT DETECTED] + printf("%lld", &buffer[1023] - buffer); // BAD [NOT DETECTED] + printf("%u", &buffer[1023] - buffer); // BAD +}