From abe696877ba789a05e2ebe64c88a6d0d2e0f7a87 Mon Sep 17 00:00:00 2001 From: chrchr Date: Mon, 12 Sep 2022 15:57:37 +0200 Subject: [PATCH] Fix #1655 wrong usage of std::string in memcpy --- lib/checkclass.cpp | 21 +++++++++++++-------- lib/checkclass.h | 2 +- test/testclass.cpp | 10 ++++++++++ 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index d081afb12c0..cce0e0fc25e 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -1353,6 +1353,10 @@ void CheckClass::checkMemset() if (numIndirToVariableType == 1) type = var->typeScope(); + + if (!type && mSettings->library.detectContainerOrIterator(var->typeStartToken())) { + memsetError(tok, tok->str(), var->getTypeName(), {}, /*isContainer*/ true); + } } } @@ -1468,15 +1472,16 @@ void CheckClass::mallocOnClassError(const Token* tok, const std::string &memfunc "since no constructor is called and class members remain uninitialized. Consider using 'new' instead.", CWE665, Certainty::normal); } -void CheckClass::memsetError(const Token *tok, const std::string &memfunc, const std::string &classname, const std::string &type) +void CheckClass::memsetError(const Token *tok, const std::string &memfunc, const std::string &classname, const std::string &type, bool isContainer) { - reportError(tok, Severity::error, "memsetClass", - "$symbol:" + memfunc +"\n" - "$symbol:" + classname +"\n" - "Using '" + memfunc + "' on " + type + " that contains a " + classname + ".\n" - "Using '" + memfunc + "' on " + type + " that contains a " + classname + " is unsafe, because constructor, destructor " - "and copy operator calls are omitted. These are necessary for this non-POD type to ensure that a valid object " - "is created.", CWE762, Certainty::normal); + const std::string typeStr = isContainer ? std::string() : (type + " that contains a "); + const std::string msg = "$symbol:" + memfunc + "\n" + "$symbol:" + classname + "\n" + "Using '" + memfunc + "' on " + typeStr + classname + ".\n" + "Using '" + memfunc + "' on " + typeStr + classname + " is unsafe, because constructor, destructor " + "and copy operator calls are omitted. These are necessary for this non-POD type to ensure that a valid object " + "is created."; + reportError(tok, Severity::error, "memsetClass", msg, CWE762, Certainty::normal); } void CheckClass::memsetErrorReference(const Token *tok, const std::string &memfunc, const std::string &type) diff --git a/lib/checkclass.h b/lib/checkclass.h index cc7bcf9cd7a..19e2ca07709 100644 --- a/lib/checkclass.h +++ b/lib/checkclass.h @@ -206,7 +206,7 @@ class CPPCHECKLIB CheckClass : public Check { void missingMemberCopyError(const Token *tok, Function::Type functionType, const std::string& classname, const std::string& varname); void operatorEqVarError(const Token *tok, const std::string &classname, const std::string &varname, bool inconclusive); void unusedPrivateFunctionError(const Token *tok, const std::string &classname, const std::string &funcname); - void memsetError(const Token *tok, const std::string &memfunc, const std::string &classname, const std::string &type); + void memsetError(const Token *tok, const std::string &memfunc, const std::string &classname, const std::string &type, bool isContainer = false); void memsetErrorReference(const Token *tok, const std::string &memfunc, const std::string &type); void memsetErrorFloat(const Token *tok, const std::string &type); void mallocOnClassError(const Token* tok, const std::string &memfunc, const Token* classTok, const std::string &classname); diff --git a/test/testclass.cpp b/test/testclass.cpp index 2aa74cedd11..683739cc131 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -3109,6 +3109,16 @@ class TestClass : public TestFixture { " memset(b, 0, sizeof(b));\n" "}"); ASSERT_EQUALS("", errout.str()); + + // #1655 + Settings s; + LOAD_LIB_2(s.library, "std.cfg"); + checkNoMemset("void f() {\n" + " char c[] = \"abc\";\n" + " std::string s;\n" + " memcpy(&s, c, strlen(c) + 1);\n" + "}\n", s); + ASSERT_EQUALS("[test.cpp:4]: (error) Using 'memcpy' on std::string.\n", errout.str()); } void memsetOnInvalid() { // Ticket #5425