diff --git a/lib/checkother.cpp b/lib/checkother.cpp index db79da181..b428cecc3 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -3764,16 +3764,19 @@ void CheckOther::checkVarFuncNullUB() if (Token::Match(tok,"[(,] NULL [,)]")) { // Locate function name in this function call. const Token *ftok = tok; + int argnr = 1; while (ftok && ftok->str() != "(") { if (ftok->str() == ")") ftok = ftok->link(); + else if (ftok->str() == ",") + ++argnr; ftok = ftok->previous(); } ftok = ftok ? ftok->previous() : NULL; if (ftok && ftok->isName()) { // If this is a variadic function then report error const Function *f = symbolDatabase->findFunctionByName(ftok->str(), scope); - if (f) { + if (f && f->argCount() <= argnr) { const Token *tok2 = f->argDef; tok2 = tok2 ? tok2->link() : NULL; // goto ')' if (Token::simpleMatch(tok2->tokAt(-3), ". . .")) diff --git a/test/testother.cpp b/test/testother.cpp index 5e923853c..1ce929b4d 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -6806,6 +6806,10 @@ private: check("void a(...);\n" "void b() { a(NULL); }"); ASSERT_EQUALS("[test.cpp:2]: (portability) Passing NULL to a function with variable number of arguments leads to undefined behaviour on some platforms.\n", errout.str()); + + check("void a(char *p, ...);\n" + "void b() { a(NULL, 2); }"); + ASSERT_EQUALS("", errout.str()); } }; diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index 9d063b21f..eb2bb5cf1 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -2086,6 +2086,8 @@ private: } void macro_NULL() { + // Let the tokenizer handle NULL. + // See ticket #4482 - UB when passing NULL to variadic function ASSERT_EQUALS("\n$0", OurPreprocessor::expandMacros("#define null 0\nnull")); ASSERT_EQUALS("\nNULL", OurPreprocessor::expandMacros("#define NULL 0\nNULL")); }