Fix FPs and crashes with byDerefCopy (#1503)

* Fix FP when inserting a range into a container

* Formatting

* Fix crash
This commit is contained in:
Paul Fultz II 2018-12-02 07:31:31 -06:00 committed by Daniel Marjamäki
parent ba564076db
commit 3e1b34dd8f
2 changed files with 39 additions and 3 deletions

View File

@ -2649,7 +2649,7 @@ struct LifetimeStore {
const Variable *var = getLifetimeVariable(tok2, errorPath);
if (!var)
continue;
for (const Token *tok3 = tok; tok != var->declEndToken(); tok3 = tok3->previous()) {
for (const Token *tok3 = tok; tok3 && tok3 != var->declEndToken(); tok3 = tok3->previous()) {
if (tok3->varId() == var->declarationId()) {
LifetimeStore{tok3, message, type} .byVal(tok, tokenlist, errorLogger, settings, pred);
break;
@ -2699,8 +2699,10 @@ static void valueFlowLifetimeFunction(Token *tok, TokenList *tokenlist, ErrorLog
const bool isPointer = endTypeTok && Token::simpleMatch(endTypeTok->previous(), "*");
Token *vartok = tok->tokAt(-2);
std::vector<const Token *> args = getArguments(tok);
if (args.size() == 2 && astCanonicalType(args[0]) == astCanonicalType(args[1]) &&
(((astIsIterator(args[0]) && astIsIterator(args[1])) || (astIsPointer(args[0]) && astIsPointer(args[1]))))) {
std::size_t n = args.size();
if (n > 1 && astCanonicalType(args[n - 2]) == astCanonicalType(args[n - 1]) &&
(((astIsIterator(args[n - 2]) && astIsIterator(args[n - 1])) ||
(astIsPointer(args[n - 2]) && astIsPointer(args[n - 1]))))) {
LifetimeStore{args.back(), "Added to container '" + vartok->str() + "'.", ValueFlow::Value::Object} .byDerefCopy(
vartok, tokenlist, errorLogger, settings);
} else if (!args.empty() && astIsPointer(args.back()) == isPointer) {

View File

@ -1420,6 +1420,19 @@ private:
"[test.cpp:5] -> [test.cpp:6] -> [test.cpp:4] -> [test.cpp:6]: (error) Non-local variable 'v' will use object that points to local variable 'i'.\n",
errout.str());
check("struct A {\n"
" std::vector<int*> m;\n"
" void f() {\n"
" int x;\n"
" std::vector<int*> v;\n"
" v.push_back(&x);\n"
" m.insert(m.end(), v.begin(), v.end());\n"
" }\n"
"};\n");
ASSERT_EQUALS(
"[test.cpp:6] -> [test.cpp:6] -> [test.cpp:6] -> [test.cpp:4] -> [test.cpp:7]: (error) Non-local variable 'm' will use object that points to local variable 'x'.\n",
errout.str());
check("struct A {\n"
" std::vector<std::string> v;\n"
" void f() {\n"
@ -1483,6 +1496,27 @@ private:
" return g([&]() { return v.data(); });\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("std::vector<int> g();\n"
"struct A {\n"
" std::vector<int> m;\n"
" void f() {\n"
" std::vector<int> v = g();\n"
" m.insert(m.end(), v.begin(), v.end());\n"
" }\n"
"};\n");
ASSERT_EQUALS("", errout.str());
check("class A {\n"
" int f( P p ) {\n"
" std::vector< S > maps;\n"
" m2.insert( m1.begin(), m1.end() );\n"
" }\n"
" struct B {};\n"
" std::map< S, B > m1;\n"
" std::map< S, B > m2;\n"
"};\n");
ASSERT_EQUALS("", errout.str());
}
void danglingLifetime() {