diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index de001bb45..484cd6ab6 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -1106,7 +1106,14 @@ void CheckStl::string_c_str() bool funcStr = false; if (Token::Match(tok2, "%var% .")) { local = isLocal(tok2); - ptrOrRef = tok2->variable() && (tok2->variable()->isPointer() || tok2->variable()->isReference()); + bool refToNonLocal = false; + if (tok2->variable() && tok2->variable()->isReference()) { + const Token *refTok = tok2->variable()->nameToken(); + refToNonLocal = true; // safe assumption is default to avoid FPs + if (Token::Match(refTok, "%var% = %var% .|;|[")) + refToNonLocal = !isLocal(refTok->tokAt(2)); + } + ptrOrRef = refToNonLocal || (tok2->variable() && tok2->variable()->isPointer()); } while (tok2) { if (Token::Match(tok2, "%var% .|::")) { diff --git a/test/teststl.cpp b/test/teststl.cpp index 20fb6cf4f..985ffe984 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -2375,6 +2375,16 @@ private: " return s.data.c_str();\n" "}"); ASSERT_EQUALS("", errout.str()); + + check("struct S {\n" // #7930 + " std::string data;\n" + "};\n" + "const char* test() {\n" + " S s;\n" + " std::string &ref = s.data;\n" + " return ref.c_str();\n" + "}"); + ASSERT_EQUALS("[test.cpp:7]: (error) Dangerous usage of c_str(). The value returned by c_str() is invalid after this call.\n", errout.str()); } void autoPointer() {