From 1da0e0c229eb646b93ba8119f2b9ec4a4308ead8 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Wed, 17 Jul 2024 15:36:46 +0200 Subject: [PATCH 1/3] Fix #12947 syntaxError for valid typedef (#6611) --- lib/tokenize.cpp | 3 ++- test/testsimplifytypedef.cpp | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 08c700794c7..cf91eabde25 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -792,7 +792,8 @@ namespace { } if (Token::Match(tok, "%name% ::")) { - if (Token::Match(mRangeType.first, "const| struct|class|union|enum %name% %name%|{")) { + if (Token::Match(mRangeType.first, "const| struct|class|union|enum %name% %name%|{") || + Token::Match(mRangeType.first, "%name% %name% ;")) { tok->originalName(tok->str()); tok->str(mRangeType.second->strAt(-1)); } else { diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index 76f53b0072f..611f9fd36fd 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -3686,6 +3686,19 @@ class TestSimplifyTypedef : public TestFixture { "} " "}"; ASSERT_EQUALS(exp3, tok(code3)); + + const char code4[] = "struct A { static const int i = 1; };\n" // #12947 + "typedef A B;\n" + "int f() {\n" + " return B::i;\n" + "}\n"; + const char exp4[] = "struct A { " + "static const int i = 1 ; " + "} ; " + "int f ( ) { " + "return A :: i ; " + "}"; + ASSERT_EQUALS(exp4, tok(code4)); } void simplifyTypedefFunction1() { From 3cb392dbc3f1dac8974cbc0217f64043780a8549 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Wed, 17 Jul 2024 18:13:54 +0200 Subject: [PATCH 2/3] Fix #12890 FP mismatchAllocDealloc with pointer to pointer (#6598) --- lib/checkmemoryleak.cpp | 6 ++++-- test/testleakautovar.cpp | 42 ++++++++++++++++------------------------ 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 76aea729a55..70e578b8d21 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -67,10 +67,12 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getAllocationType(const Token *tok2, return No; if (tok2->str() == "::") tok2 = tok2->next(); + while (Token::Match(tok2, "%name% :: %type%")) + tok2 = tok2->tokAt(2); if (!tok2->isName()) return No; - if (!Token::Match(tok2, "%name% ::|. %type%")) { + if (!Token::Match(tok2, "%name% . %type%")) { // Using realloc.. AllocType reallocType = getReallocationType(tok2, varid); if (reallocType != No) @@ -124,7 +126,7 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getAllocationType(const Token *tok2, } } - while (Token::Match(tok2,"%name% ::|. %type%")) + while (Token::Match(tok2,"%name% . %type%")) tok2 = tok2->tokAt(2); // User function diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index 9e50ddfee9d..286c1a75c24 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -33,29 +33,7 @@ class TestLeakAutoVar : public TestFixture { Settings settings; void run() override { - constexpr char xmldata[] = "\n" - "\n" - " \n" - " \n" - " malloc\n" - " realloc\n" - " free\n" - " \n" - " \n" - " socket\n" - " close\n" - " \n" - " \n" - " fopen\n" - " freopen\n" - " fclose\n" - " \n" - " \n" - " \n" - " \n" - " \n" - ""; - settings = settingsBuilder(settings).libraryxml(xmldata, sizeof(xmldata)).build(); + settings = settingsBuilder(settings).library("std.cfg").build(); // Assign TEST_CASE(assign1); @@ -462,9 +440,10 @@ class TestLeakAutoVar : public TestFixture { } void assign22() { // #9139 + const Settings s = settingsBuilder().library("posix.cfg").build(); check("void f(char tempFileName[256]) {\n" " const int fd = socket(AF_INET, SOCK_PACKET, 0 );\n" - "}", true); + "}", true, &s); ASSERT_EQUALS("[test.cpp:3]: (error) Resource leak: fd\n", errout_str()); check("void f() {\n" @@ -622,6 +601,19 @@ class TestLeakAutoVar : public TestFixture { " delete[] li.front().m_p;\n" "}\n", true); ASSERT_EQUALS("", errout_str()); + + check("struct S {\n" // #12890 + " int** p;\n" + " S() {\n" + " p = std::malloc(sizeof(int*));\n" + " p[0] = new int;\n" + " }\n" + " ~S() {\n" + " delete p[0];\n" + " std::free(p);\n" + " }\n" + "};\n", true); + ASSERT_EQUALS("", errout_str()); } void assign26() { @@ -652,7 +644,7 @@ class TestLeakAutoVar : public TestFixture { check("void f() {\n" " std::string *str = new std::string;" "}", true); - TODO_ASSERT_EQUALS("[test.cpp:2]: (error) Memory leak: str\n", "", errout_str()); + ASSERT_EQUALS("[test.cpp:2]: (error) Memory leak: str\n", errout_str()); check("class TestType {\n" // #9028 "public:\n" From 5aebb2cdaf62c02db6dd1f0e8e19c9ec3806d221 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Fri, 19 Jul 2024 10:22:38 +0200 Subject: [PATCH 3/3] Fix #12506 FP memleak when not calling freeaddrinfo() in error path (#6604) --- lib/checkleakautovar.cpp | 48 +++++++++++++++++++++++++++------------- test/cfg/posix.c | 11 +++++++++ 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index 80a3a862893..432b786edee 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -263,6 +263,30 @@ static const Token * isFunctionCall(const Token * nameToken) return nullptr; } +static const Token* getOutparamAllocation(const Token* tok, const Settings& settings) +{ + if (!tok) + return nullptr; + int argn{}; + const Token* ftok = getTokenArgumentFunction(tok, argn); + if (!ftok) + return nullptr; + if (const Library::AllocFunc* allocFunc = settings.library.getAllocFuncInfo(ftok)) { + if (allocFunc->arg == argn + 1) + return ftok; + } + return nullptr; +} + +static const Token* getReturnValueFromOutparamAlloc(const Token* alloc, const Settings& settings) +{ + if (const Token* ftok = getOutparamAllocation(alloc, settings)) { + if (Token::simpleMatch(ftok->astParent()->astParent(), "=")) + return ftok->next()->astParent()->astOperand1(); + } + return nullptr; +} + bool CheckLeakAutoVar::checkScope(const Token * const startToken, VarInfo &varInfo, std::set notzero, @@ -526,6 +550,15 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken, if (astIsVariableComparison(tok3, "!=", "0", &vartok) && (notzero.find(vartok->varId()) != notzero.end())) varInfo2.clear(); + + if (std::any_of(varInfo1.alloctype.begin(), varInfo1.alloctype.end(), [&](const std::pair& info) { + if (info.second.status != VarInfo::ALLOC) + return false; + const Token* ret = getReturnValueFromOutparamAlloc(info.second.allocTok, *mSettings); + return ret && ret->varId() && ret->varId() == vartok->varId(); + })) { + varInfo1.clear(); + } } else if (isVarTokComparison(tok3, &vartok, alloc_failed_conds)) { varInfo1.reallocToAlloc(vartok->varId()); varInfo1.erase(vartok->varId()); @@ -1056,21 +1089,6 @@ void CheckLeakAutoVar::leakIfAllocated(const Token *vartok, } } -static const Token* getOutparamAllocation(const Token* tok, const Settings& settings) -{ - if (!tok) - return nullptr; - int argn{}; - const Token* ftok = getTokenArgumentFunction(tok, argn); - if (!ftok) - return nullptr; - if (const Library::AllocFunc* allocFunc = settings.library.getAllocFuncInfo(ftok)) { - if (allocFunc->arg == argn + 1) - return ftok; - } - return nullptr; -} - void CheckLeakAutoVar::ret(const Token *tok, VarInfo &varInfo, const bool isEndOfScope) { const std::map &alloctype = varInfo.alloctype; diff --git a/test/cfg/posix.c b/test/cfg/posix.c index b4b8c9e4985..f135ea7d6de 100644 --- a/test/cfg/posix.c +++ b/test/cfg/posix.c @@ -1046,6 +1046,17 @@ void memleak_getaddrinfo() // #6994 // cppcheck-suppress memleak } +void memleak_getaddrinfo_if() // #12506 +{ + struct addrinfo hints = {}; + struct addrinfo* addrs; + int err = getaddrinfo("example.com", "https", &hints, &addrs); + if (err != 0) {} + else { + freeaddrinfo(addrs); + } +} + void memleak_mmap(int fd) { // cppcheck-suppress [unusedAllocatedMemory, unreadVariable, constVariablePointer]