diff --git a/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql b/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql index 272ef8369d0e..75fe855c6f91 100644 --- a/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql +++ b/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql @@ -171,7 +171,9 @@ where not arg.isAffectedByMacro() and not arg.isFromUninstantiatedTemplate(_) and not actual.stripType() instanceof ErroneousType and - not arg.(Call).mayBeFromImplicitlyDeclaredFunction() + not arg.(Call).mayBeFromImplicitlyDeclaredFunction() and + // Make sure that the format function definition is consistent + count(ffc.getTarget().getFormatParameterIndex()) = 1 select arg, "This format specifier for type '" + expected.getName() + "' does not match the argument type '" + actual.getUnspecifiedType().getName() + "'." diff --git a/cpp/ql/src/change-notes/2025-01-31-format-args.md b/cpp/ql/src/change-notes/2025-01-31-format-args.md new file mode 100644 index 000000000000..41f3d6bb202e --- /dev/null +++ b/cpp/ql/src/change-notes/2025-01-31-format-args.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The "Wrong type of arguments to formatting function" query (`cpp/wrong-type-format-argument`) now produces fewer FPs if the formatting function has multiple definitions. diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Buildless/tests.c b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Buildless/tests.c index 175d2f23182d..c5b3d1df493a 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Buildless/tests.c +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Buildless/tests.c @@ -10,3 +10,21 @@ void f(UNKNOWN_CHAR * str) { fprintf(0, "%s", ""); // GOOD printf("%s", str); // GOOD - erroneous type is ignored } + +#define va_list void* +#define va_start(x, y) x = 0; +#define va_arg(x, y) ((y)x) +#define va_end(x) +int vprintf(const char * format, va_list args); + +int my_printf(const char * format, ...) { + va_list args; + va_start(args, format); + int result = vprintf(format, args); + va_end(args); + return result; +} + +void linker_awareness_test() { + my_printf("%s%d", "", 1); // GOOD +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Buildless/tests2.c b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Buildless/tests2.c new file mode 100644 index 000000000000..69f5761d6a85 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Buildless/tests2.c @@ -0,0 +1,14 @@ +#define va_list void* +#define va_start(x, y) x = 0; +#define va_arg(x, y) ((y)x) +#define va_end(x) + +int vprintf(const char * format, va_list args); + +int my_printf(void * p,const char * format, ...) { + va_list args; + va_start(args, format); + int result = vprintf(format, args); + va_end(args); + return result; +}