Find iterator mismatch when using temporary containers (#3579)

This commit is contained in:
Paul Fultz II 2021-12-04 05:55:56 -06:00 committed by GitHub
parent c14920218c
commit 8dcea26c10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 29 additions and 8 deletions

View File

@ -344,9 +344,14 @@ void CheckStl::iteratorsError(const Token* tok, const Token* containerTok, const
void CheckStl::iteratorsError(const Token* tok, const Token* containerTok, const std::string& containerName)
{
std::list<const Token*> callstack = { tok, containerTok };
reportError(callstack, Severity::error, "iterators3",
"$symbol:" + containerName + "\n"
"Same iterator is used with containers '" + containerName + "' that are defined in different scopes.", CWE664, Certainty::normal);
reportError(callstack,
Severity::error,
"iterators3",
"$symbol:" + containerName +
"\n"
"Same iterator is used with containers '$symbol' that are temporaries or defined in different scopes.",
CWE664,
Certainty::normal);
}
// Error message used when dereferencing an iterator that has been erased..
@ -709,8 +714,11 @@ static bool isSameIteratorContainerExpression(const Token* tok1,
const Library& library,
ValueFlow::Value::LifetimeKind kind = ValueFlow::Value::LifetimeKind::Iterator)
{
if (isSameExpression(true, false, tok1, tok2, library, false, false))
if (isSameExpression(true, false, tok1, tok2, library, false, false)) {
if (astIsContainerOwned(tok1) && isTemporary(true, tok1, &library))
return false;
return true;
}
if (kind == ValueFlow::Value::LifetimeKind::Address) {
return isSameExpression(true, false, getAddressContainer(tok1), getAddressContainer(tok2), library, false, false);
}

View File

@ -1305,7 +1305,9 @@ private:
" }\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:4]: (error) Same iterator is used with containers 'l1' that are defined in different scopes.\n", errout.str());
ASSERT_EQUALS(
"[test.cpp:7] -> [test.cpp:4]: (error) Same iterator is used with containers 'l1' that are temporaries or defined in different scopes.\n",
errout.str());
check("void foo()\n"
"{\n"
@ -1320,7 +1322,7 @@ private:
"}");
TODO_ASSERT_EQUALS(
"[test.cpp:7] -> [test.cpp:4]: (error) Same iterator is used with containers 'l1' that are defined in different scopes.\n",
"[test.cpp:7] -> [test.cpp:7]: (error) Same iterator is used with containers 'l1' that are defined in different scopes.\n[test.cpp:7]: (error) Dangerous comparison using operator< on iterator.\n",
"[test.cpp:7] -> [test.cpp:7]: (error) Same iterator is used with containers 'l1' that are temporaries or defined in different scopes.\n[test.cpp:7]: (error) Dangerous comparison using operator< on iterator.\n",
errout.str());
check("void foo()\n"
@ -1336,7 +1338,7 @@ private:
" }\n"
"}");
ASSERT_EQUALS(
"[test.cpp:8] -> [test.cpp:4]: (error) Same iterator is used with containers 'l1' that are defined in different scopes.\n",
"[test.cpp:8] -> [test.cpp:4]: (error) Same iterator is used with containers 'l1' that are temporaries or defined in different scopes.\n",
errout.str());
check("void foo()\n"
@ -1352,7 +1354,18 @@ private:
" }\n"
"}");
ASSERT_EQUALS(
"[test.cpp:8] -> [test.cpp:7]: (error) Same iterator is used with containers 'l1' that are defined in different scopes.\n",
"[test.cpp:8] -> [test.cpp:7]: (error) Same iterator is used with containers 'l1' that are temporaries or defined in different scopes.\n",
errout.str());
check("std::set<int> g() {\n"
" static const std::set<int> s = {1};\n"
" return s;\n"
"}\n"
"void f() {\n"
" if (g().find(2) == g().end()) {}\n"
"}\n");
ASSERT_EQUALS(
"[test.cpp:6] -> [test.cpp:6]: (error) Same iterator is used with containers 'g()' that are temporaries or defined in different scopes.\n",
errout.str());
}