From c24527dbdeefee58ed0b68bd7fe669b339b3b02a Mon Sep 17 00:00:00 2001 From: PKEuS Date: Mon, 4 Mar 2013 02:47:29 -0800 Subject: [PATCH] Improved handling of dereferences in CheckClass::noMemset(), fixing false negatives and false positives related to multidimensional arrays and arrays of pointers. --- lib/checkclass.cpp | 26 ++++++++++++++++++++++---- test/testclass.cpp | 18 ++++++++++++++++++ 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index b695bead8..24474eb1f 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -838,10 +838,28 @@ void CheckClass::noMemset() typeTok = arg3->tokAt(3); else if (Token::simpleMatch(arg3, "sizeof ( * this ) )") || Token::simpleMatch(arg1, "this ,")) { type = findFunctionOf(arg3->scope()); - } else if (Token::Match(arg1, "&| %var% ,")) { - const Variable *var = arg1->str() == "&" ? arg1->next()->variable() : arg1->variable(); - if (var && (arg1->str() == "&" || var->isPointer() || var->isArray())) - type = var->type(); + } else if (Token::Match(arg1, "&|*|%var%")) { + int derefs = 1; + for (;; arg1 = arg1->next()) { + if (arg1->str() == "&") + derefs--; + else if (arg1->str() == "*") + derefs++; + else + break; + } + + const Variable *var = arg1->variable(); + if (var && arg1->strAt(1) == ",") { + if (var->isPointer()) + derefs--; + if (var->isArray()) + derefs -= var->dimensions().size(); + + if (derefs == 0) + type = var->type(); + } + } // No type defined => The tokens didn't match diff --git a/test/testclass.cpp b/test/testclass.cpp index c6635972f..583b0674e 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -2305,6 +2305,24 @@ private: " memset(a, 0, 100);\n" "}"); ASSERT_EQUALS("", errout.str()); // #4460 + + checkNoMemset("struct C {\n" + " std::string s;\n" + "};\n" + "int foo() {\n" + " C* c1[10][10];\n" + " C* c2[10];\n" + " C c3[10][10];\n" + " memset(**c1, 0, 10);\n" + " memset(*c1, 0, 10);\n" + " memset(*c2, 0, 10);\n" + " memset(*c3, 0, 10);\n" + " memset(c2, 0, 10);\n" + " memset(c3, 0, 10);\n" + "}"); + ASSERT_EQUALS("[test.cpp:8]: (error) Using 'memset' on struct that contains a 'std::string'.\n" + "[test.cpp:10]: (error) Using 'memset' on struct that contains a 'std::string'.\n" + "[test.cpp:11]: (error) Using 'memset' on struct that contains a 'std::string'.\n", errout.str()); } void mallocOnClass() {