checkstl: Check for invalid pointer to vector element

This commit is contained in:
Daniel Marjamäki 2009-04-28 21:18:02 +02:00
parent 8075cd8b9d
commit f9795988eb
3 changed files with 52 additions and 1 deletions

View File

@ -222,6 +222,48 @@ void CheckStl::eraseError(const Token *tok)
void CheckStl::pushback()
{
// Pointer can become invalid after push_back or push_front..
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
{
if (Token::Match(tok, "%var% = & %var% ["))
{
const unsigned int pointerId(tok->varId());
const unsigned int containerId(tok->tokAt(3)->varId());
if (pointerId == 0 || containerId == 0)
continue;
int indent = 0;
bool invalidPointer = false;
for (const Token *tok2 = tok; indent >= 0 && tok2; tok2 = tok2->next())
{
if (tok2->str() == "{" || tok2->str() == "(")
++indent;
else if (tok2->str() == "}" || tok2->str() == ")")
{
if (indent == 0 && Token::simpleMatch(tok2, ") {"))
tok2 = tok2->next();
else
--indent;
}
// push_back on vector..
if (Token::Match(tok2, "%varid% . push_front|push_back", containerId))
invalidPointer = true;
// Using invalid pointer..
if (invalidPointer && tok2->varId() == pointerId)
{
if (Token::simpleMatch(tok2->previous(), "*"))
invalidPointerError(tok2, tok2->str());
else if (Token::simpleMatch(tok2->next(), "."))
invalidPointerError(tok2, tok2->str());
break;
}
}
}
}
// Iterator becomes invalid after push_back or push_front..
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
{
if (Token::Match(tok, "vector <"))
@ -284,6 +326,13 @@ void CheckStl::pushbackError(const Token *tok, const std::string &iterator_name)
}
// Error message for bad iterator usage..
void CheckStl::invalidPointerError(const Token *tok, const std::string &pointer_name)
{
reportError(tok, "error", "pushback", "Invalid pointer '" + pointer_name + "' after push_back / push_front");
}
void CheckStl::stlBoundries()

View File

@ -91,6 +91,7 @@ private:
void iteratorsError(const Token *tok, const std::string &container1, const std::string &container2);
void eraseError(const Token *tok);
void pushbackError(const Token *tok, const std::string &iterator_name);
void invalidPointerError(const Token *tok, const std::string &pointer_name);
void stlBoundriesError(const Token *tok);
void getErrorMessages()
@ -99,6 +100,7 @@ private:
stlOutOfBoundsError(0, "i", "foo");
eraseError(0);
pushbackError(0, "iterator");
invalidPointerError(0, "pointer");
stlBoundriesError(0);
}
};

View File

@ -287,7 +287,7 @@ private:
" ints.push_back(2);\n"
" *first;\n"
"}\n");
TODO_ASSERT_EQUALS("[test.cpp:6]: (error) After push_back or push_front, the pointer 'first' may be invalid\n", errout.str());
ASSERT_EQUALS("[test.cpp:7]: (error) Invalid pointer 'first' after push_back / push_front\n", errout.str());
}