From a2d9a42a660342c7f7207c9622a02e1c4b5f0dba Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:54:54 +0200 Subject: [PATCH 1/8] Update testnullpointer.cpp --- test/testnullpointer.cpp | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/test/testnullpointer.cpp b/test/testnullpointer.cpp index eb61c781b13..a9ce5ff6f38 100644 --- a/test/testnullpointer.cpp +++ b/test/testnullpointer.cpp @@ -3489,8 +3489,7 @@ class TestNullPointer : public TestFixture { " printf(\"%s\", s);\n" "}"); ASSERT_EQUALS( - "[test.cpp:3:18]: (error) Null pointer dereference: s [nullPointer]\n" - "[test.cpp:3:18]: (error) Null pointer dereference [nullPointer]\n", + "[test.cpp:3:18]: (error) Null pointer dereference: s [nullPointer]\n", errout_str()); check("void f() {\n" @@ -3514,8 +3513,7 @@ class TestNullPointer : public TestFixture { " printf(\"%u%s\", 123, s);\n" "}"); ASSERT_EQUALS( - "[test.cpp:3:25]: (error) Null pointer dereference: s [nullPointer]\n" - "[test.cpp:3:25]: (error) Null pointer dereference [nullPointer]\n", + "[test.cpp:3:25]: (error) Null pointer dereference: s [nullPointer]\n", errout_str()); @@ -3560,16 +3558,14 @@ class TestNullPointer : public TestFixture { " sscanf(s, \"%s\", 0);\n" "}"); ASSERT_EQUALS( - "[test.cpp:2:21]: (error) Null pointer dereference [nullPointer]\n" - "[test.cpp:2:21]: (error) Null pointer dereference [nullPointer]\n", // duplicate + "[test.cpp:2:21]: (error) Null pointer dereference [nullPointer]\n", errout_str()); check("void f() {\n" " scanf(\"%d\", 0);\n" "}"); ASSERT_EQUALS( - "[test.cpp:2:17]: (error) Null pointer dereference [nullPointer]\n" - "[test.cpp:2:17]: (error) Null pointer dereference [nullPointer]\n", // duplicate + "[test.cpp:2:17]: (error) Null pointer dereference [nullPointer]\n", errout_str()); check("void f(char* foo) {\n" @@ -3590,9 +3586,7 @@ class TestNullPointer : public TestFixture { " sscanf(dummy, \"%d\", iVal);\n" "}"); ASSERT_EQUALS( - "[test.cpp:3:25]: (error) Null pointer dereference: iVal [nullPointer]\n" - "[test.cpp:3:25]: (error) Null pointer dereference [nullPointer]\n" - "[test.cpp:3:25]: (error) Null pointer dereference [nullPointer]\n", // duplicate + "[test.cpp:3:25]: (error) Null pointer dereference: iVal [nullPointer]\n", errout_str()); check("void f(char *dummy) {\n" @@ -3611,8 +3605,7 @@ class TestNullPointer : public TestFixture { " sscanf(dummy, \"%*d%u\", 0);\n" "}"); ASSERT_EQUALS( - "[test.cpp:2:28]: (error) Null pointer dereference [nullPointer]\n" - "[test.cpp:2:28]: (error) Null pointer dereference [nullPointer]\n", // duplicate + "[test.cpp:2:28]: (error) Null pointer dereference [nullPointer]\n", errout_str()); } @@ -4333,8 +4326,7 @@ class TestNullPointer : public TestFixture { Library library; ASSERT(LibraryHelper::loadxmldata(library, xmldata, sizeof(xmldata))); - std::list null; - CheckNullPointer::parseFunctionCall(*xtok, null, library); + const std::list null = CheckNullPointer::parseFunctionCall(*xtok, library); ASSERT_EQUALS(0U, null.size()); } @@ -4352,8 +4344,7 @@ class TestNullPointer : public TestFixture { Library library; ASSERT(LibraryHelper::loadxmldata(library, xmldata, sizeof(xmldata))); - std::list null; - CheckNullPointer::parseFunctionCall(*xtok, null, library); + const std::list null = CheckNullPointer::parseFunctionCall(*xtok, library); ASSERT_EQUALS(1U, null.size()); ASSERT_EQUALS("a", null.front()->str()); } From 8710deb512f01ae6d3c961033e0cebccf07f3758 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:55:24 +0200 Subject: [PATCH 2/8] Update checknullpointer.cpp --- lib/checknullpointer.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index 42b9f76646e..8d01998e835 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -66,13 +66,13 @@ static bool checkNullpointerFunctionCallPlausibility(const Function* func, unsig * @param library --library files data * @param checkNullArg perform isnullargbad check for each argument? */ -void CheckNullPointer::parseFunctionCall(const Token &tok, std::list &var, const Library &library, bool checkNullArg) +std::list CheckNullPointer::parseFunctionCall(const Token &tok, const Library &library, bool checkNullArg) { if (Token::Match(&tok, "%name% ( )") || !tok.tokAt(2)) - return; + return {}; const std::vector args = getArguments(&tok); - + std::list var; for (int argnr = 1; argnr <= args.size(); ++argnr) { const Token *param = args[argnr - 1]; if ((!checkNullArg || library.isnullargbad(&tok, argnr)) && checkNullpointerFunctionCallPlausibility(tok.function(), argnr)) @@ -87,14 +87,14 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list= args.size()) - return; + return var; // 1st parameter.. if (Token::Match(&tok, "snprintf|vsnprintf|fnprintf|vfnprintf") && args.size() > 1 && !(args[1] && args[1]->hasKnownIntValue() && args[1]->getKnownIntValue() == 0)) // Only if length (second parameter) is not zero var.push_back(args[0]); if (args[formatStringArgNr]->tokType() != Token::eString) - return; + return var; const std::string &formatString = args[formatStringArgNr]->strValue(); int argnr = formatStringArgNr + 1; const bool scan = library.formatstr_scan(&tok); @@ -116,7 +116,7 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::listprevious(); } if (ftok && ftok->previous()) { - std::list varlist; - parseFunctionCall(*ftok->previous(), varlist, settings.library, checkNullArg); + const std::list varlist = parseFunctionCall(*ftok->previous(), settings.library, checkNullArg); if (std::find(varlist.cbegin(), varlist.cend(), tok) != varlist.cend()) { return true; } @@ -376,8 +376,7 @@ void CheckNullPointer::nullConstantDereference() if (var && !var->isPointer() && !var->isArray() && var->isStlStringType()) nullPointerError(tok); } else { // function call - std::list var; - parseFunctionCall(*tok, var, mSettings->library); + const std::list var = parseFunctionCall(*tok, mSettings->library); // is one of the var items a NULL pointer? for (const Token *vartok : var) { @@ -456,6 +455,8 @@ void CheckNullPointer::nullPointerError(const Token *tok, const std::string &var reportError(tok, Severity::warning, "nullPointerOutOfResources", "Null pointer dereference", CWE_NULL_POINTER_DEREFERENCE, Certainty::normal); return; } + if (diag(tok)) + return; if (!value) { reportError(tok, Severity::error, "nullPointer", "Null pointer dereference", CWE_NULL_POINTER_DEREFERENCE, inconclusive ? Certainty::inconclusive : Certainty::normal); From b98d3277989c134f4aaaa17f9be4eb36b8987b94 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:55:52 +0200 Subject: [PATCH 3/8] Update checknullpointer.h --- lib/checknullpointer.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/checknullpointer.h b/lib/checknullpointer.h index d28927d19e9..a63507c950d 100644 --- a/lib/checknullpointer.h +++ b/lib/checknullpointer.h @@ -72,8 +72,7 @@ class CPPCHECKLIB CheckNullPointer : public Check { * @param var variables that the function read / write. * @param library --library files data */ - static void parseFunctionCall(const Token &tok, - std::list &var, + static std::list parseFunctionCall(const Token &tok, const Library &library, bool checkNullArg = true); /** @brief This constructor is used when running checks. */ @@ -125,6 +124,10 @@ class CPPCHECKLIB CheckNullPointer : public Check { void arithmetic(); void pointerArithmeticError(const Token* tok, const ValueFlow::Value *value, bool inconclusive); void redundantConditionWarning(const Token* tok, const ValueFlow::Value *value, const Token *condition, bool inconclusive); + + bool diag(const Token* tok) { return !mDiag.emplace(tok).second; } + + std::set mDiag; }; /// @} //--------------------------------------------------------------------------- From 6e235c05aa4ebec489001c660de8e0836e1cfe3a Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Tue, 31 Mar 2026 11:05:29 +0200 Subject: [PATCH 4/8] Update checknullpointer.h --- lib/checknullpointer.h | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/checknullpointer.h b/lib/checknullpointer.h index a63507c950d..d5bbe69ce0d 100644 --- a/lib/checknullpointer.h +++ b/lib/checknullpointer.h @@ -26,6 +26,7 @@ #include "config.h" #include +#include #include class ErrorLogger; From 9bfe417d7ce7a919f511e58f6f4c36a45921ee1d Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Tue, 31 Mar 2026 11:15:01 +0200 Subject: [PATCH 5/8] Update checknullpointer.h --- lib/checknullpointer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/checknullpointer.h b/lib/checknullpointer.h index d5bbe69ce0d..bdbb4133df2 100644 --- a/lib/checknullpointer.h +++ b/lib/checknullpointer.h @@ -70,8 +70,8 @@ class CPPCHECKLIB CheckNullPointer : public Check { /** * @brief parse a function call and extract information about variable usage * @param tok first token - * @param var variables that the function read / write. * @param library --library files data + * @return list of variables that the function reads / writes. */ static std::list parseFunctionCall(const Token &tok, const Library &library, bool checkNullArg = true); From 3d26fa058bb4567f04fb76c6dee0e6d66331f614 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Tue, 31 Mar 2026 11:27:12 +0200 Subject: [PATCH 6/8] Update checknullpointer.cpp --- lib/checknullpointer.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index 8d01998e835..02c5cd8c812 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -59,13 +59,6 @@ static bool checkNullpointerFunctionCallPlausibility(const Function* func, unsig return !func || (func->argCount() >= arg && func->getArgumentVar(arg - 1) && func->getArgumentVar(arg - 1)->isPointer()); } -/** - * @brief parse a function call and extract information about variable usage - * @param tok first token - * @param var variables that the function read / write. - * @param library --library files data - * @param checkNullArg perform isnullargbad check for each argument? - */ std::list CheckNullPointer::parseFunctionCall(const Token &tok, const Library &library, bool checkNullArg) { if (Token::Match(&tok, "%name% ( )") || !tok.tokAt(2)) From acdf1afe7d571e04aa9c57bf9b5df4b5d29f8f64 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Tue, 31 Mar 2026 13:59:21 +0200 Subject: [PATCH 7/8] Update checknullpointer.h --- lib/checknullpointer.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/checknullpointer.h b/lib/checknullpointer.h index bdbb4133df2..574b0cb2e92 100644 --- a/lib/checknullpointer.h +++ b/lib/checknullpointer.h @@ -73,8 +73,7 @@ class CPPCHECKLIB CheckNullPointer : public Check { * @param library --library files data * @return list of variables that the function reads / writes. */ - static std::list parseFunctionCall(const Token &tok, - const Library &library, bool checkNullArg = true); + static std::list parseFunctionCall(const Token &tok, const Library &library, bool checkNullArg = true); /** @brief This constructor is used when running checks. */ CheckNullPointer(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) @@ -126,7 +125,9 @@ class CPPCHECKLIB CheckNullPointer : public Check { void pointerArithmeticError(const Token* tok, const ValueFlow::Value *value, bool inconclusive); void redundantConditionWarning(const Token* tok, const ValueFlow::Value *value, const Token *condition, bool inconclusive); - bool diag(const Token* tok) { return !mDiag.emplace(tok).second; } + bool diag(const Token* tok) { + return !mDiag.emplace(tok).second; + } std::set mDiag; }; From 7c09aa04201d940d936afb9a40e84a8ad692c161 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Thu, 2 Apr 2026 08:42:45 +0200 Subject: [PATCH 8/8] Update checknullpointer.h [skip ci] --- lib/checknullpointer.h | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/checknullpointer.h b/lib/checknullpointer.h index 574b0cb2e92..c02feae303e 100644 --- a/lib/checknullpointer.h +++ b/lib/checknullpointer.h @@ -71,6 +71,7 @@ class CPPCHECKLIB CheckNullPointer : public Check { * @brief parse a function call and extract information about variable usage * @param tok first token * @param library --library files data + * @param checkNullArg perform isnullargbad check for each argument? * @return list of variables that the function reads / writes. */ static std::list parseFunctionCall(const Token &tok, const Library &library, bool checkNullArg = true);