From da8ad9ce190fab2e5cad499a1fd33ce08bcd05fd Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Sat, 12 Sep 2020 18:46:01 +0200 Subject: [PATCH 1/2] memleakOnRealloc: Don't warn if pointer is NULL in condition --- lib/checkmemoryleak.cpp | 5 +++++ test/testmemleak.cpp | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 43c0664e2..4bcbc6625 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -550,6 +550,11 @@ void CheckMemoryLeakInFunction::checkReallocUsage() Token::findmatch(scope->bodyStart, "[{};] %varid% = *| %name% .| %name%| [;=]", tok, tok->varId())) continue; + // Check if the argument is known to be null, which means it is not a memory leak + if (arg->hasKnownIntValue() && arg->getKnownIntValue() == 0) { + continue; + } + const Token* tokEndRealloc = reallocTok->linkAt(1); // Check that the allocation isn't followed immediately by an 'if (!var) { error(); }' that might handle failure if (Token::simpleMatch(tokEndRealloc->next(), "; if (") && diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index b70b35921..1b598ef84 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -201,7 +201,7 @@ private: " free(a);\n" "}"); - TODO_ASSERT_EQUALS("", "[test.cpp:4]: (error) Common realloc mistake: 'a' nulled but not freed upon failure\n", errout.str()); + ASSERT_EQUALS("", errout.str()); } void realloc4() { @@ -296,7 +296,7 @@ private: " return;\n" " free(a);\n" "}"); - TODO_ASSERT_EQUALS("", "[test.cpp:4]: (error) Common realloc mistake: 'a' nulled but not freed upon failure\n", errout.str()); + ASSERT_EQUALS("", errout.str()); } void realloc13() { From 791051ced0b37198d8de51145239930bae087dff Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Fri, 31 Jul 2020 01:44:33 +0200 Subject: [PATCH 2/2] Fix #9228 (FN common realloc mistake with assignment of NULL) Do not match for assignments with NULL. --- lib/checkmemoryleak.cpp | 2 +- test/testmemleak.cpp | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 4bcbc6625..c19c3e2e3 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -547,7 +547,7 @@ void CheckMemoryLeakInFunction::checkReallocUsage() // Check that another copy of the pointer wasn't saved earlier in the function if (Token::findmatch(scope->bodyStart, "%name% = %varid% ;", tok, tok->varId()) || - Token::findmatch(scope->bodyStart, "[{};] %varid% = *| %name% .| %name%| [;=]", tok, tok->varId())) + Token::findmatch(scope->bodyStart, "[{};] %varid% = *| %var% .| %var%| [;=]", tok, tok->varId())) continue; // Check if the argument is known to be null, which means it is not a memory leak diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index 1b598ef84..4d98b15c7 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -169,6 +169,7 @@ private: TEST_CASE(realloc21); TEST_CASE(realloc22); TEST_CASE(realloc23); + TEST_CASE(realloc24); // #9228 TEST_CASE(reallocarray1); } @@ -410,6 +411,35 @@ private: ASSERT_EQUALS("", errout.str()); } + void realloc24() { // #9228 + check("void f() {\n" + "void *a = NULL;\n" + "a = realloc(a, 20);\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + check("void f() {\n" + "void *a = NULL;\n" + "a = malloc(10);\n" + "a = realloc(a, 20);\n" + "}"); + ASSERT_EQUALS("[test.cpp:4]: (error) Common realloc mistake: \'a\' nulled but not freed upon failure\n", errout.str()); + + check("void f() {\n" + "void *a = std::nullptr;\n" + "a = malloc(10);\n" + "a = realloc(a, 20);\n" + "}"); + ASSERT_EQUALS("[test.cpp:4]: (error) Common realloc mistake: \'a\' nulled but not freed upon failure\n", errout.str()); + + check("void f(char *b) {\n" + "void *a = NULL;\n" + "a = b;\n" + "a = realloc(a, 20);\n" + "}"); + ASSERT_EQUALS("", errout.str()); + } + void reallocarray1() { check("void foo()\n" "{\n"