#7208 Cppcheck hangs with 100% CPU load in CheckOther::checkNegativeBitwiseShift (invalidcode). TokenList::validateAst() is running consistency checks on AST

This commit is contained in:
Alexander Mai 2015-12-12 15:39:38 +01:00
parent e0e8c3fe60
commit 9a847d7b14
3 changed files with 50 additions and 0 deletions

View File

@ -1057,6 +1057,34 @@ void TokenList::createAst()
for (Token *tok = _front; tok; tok = tok ? tok->next() : NULL) { for (Token *tok = _front; tok; tok = tok ? tok->next() : NULL) {
tok = createAstAtToken(tok, isCPP()); tok = createAstAtToken(tok, isCPP());
} }
validateAst();
}
void TokenList::validateAst()
{
// Verify that ast looks ok
for (const Token *tok = _front; tok; tok = tok->next()) {
// Syntax error if binary operator only has 1 operand
if ((tok->isAssignmentOp() || tok->isComparisonOp() || Token::Match(tok,"[|^/%]")) && tok->astOperand1() && !tok->astOperand2())
throw InternalError(tok, "Syntax Error: AST broken, binary operator has only one operand.", InternalError::SYNTAX);
// Syntax error if we encounter "?" with operand2 that is not ":"
if (tok->astOperand2() && tok->str() == "?" && tok->astOperand2()->str() != ":")
throw InternalError(tok, "Syntax Error: AST broken, ternary operator lacks ':'.", InternalError::SYNTAX);
// check for endless recursion
const Token* parent=tok;
while (parent = parent->astParent()) {
if (parent==tok)
throw InternalError(tok, "AST broken: endless recursion from '" + tok->str() + "'", InternalError::SYNTAX);
}
}
}
void TokenList::cppcheckError(const Token *tok) const
{
throw InternalError(tok, "Analysis failed - inconsisten AST. If the code is valid then please report this failure.", InternalError::INTERNAL);
} }
const std::string& TokenList::file(const Token *tok) const const std::string& TokenList::file(const Token *tok) const

View File

@ -126,9 +126,24 @@ public:
*/ */
unsigned long long calculateChecksum() const; unsigned long long calculateChecksum() const;
/**
* Create abstract syntax tree.
*/
void createAst(); void createAst();
/**
* Create abstract syntax tree.
*/
void validateAst();
private: private:
/**
* Send error message to error logger about internal bug.
* @param tok the token that this bug concerns.
*/
void cppcheckError(const Token *tok) const;
/** Disable copy constructor, no implementation */ /** Disable copy constructor, no implementation */
TokenList(const TokenList &); TokenList(const TokenList &);

View File

@ -210,6 +210,7 @@ private:
TEST_CASE(garbageCode159); // #7119 TEST_CASE(garbageCode159); // #7119
TEST_CASE(garbageCode160); // #7190 TEST_CASE(garbageCode160); // #7190
TEST_CASE(garbageCode161); // #7200 TEST_CASE(garbageCode161); // #7200
TEST_CASE(garbageCode162); // #7208
TEST_CASE(garbageValueFlow); TEST_CASE(garbageValueFlow);
TEST_CASE(garbageSymbolDatabase); TEST_CASE(garbageSymbolDatabase);
TEST_CASE(garbageAST); TEST_CASE(garbageAST);
@ -1386,6 +1387,12 @@ private:
//7200 //7200
ASSERT_THROW(checkCode("{ }{ if () try { } catch (...)} B : : ~B { }"), InternalError); ASSERT_THROW(checkCode("{ }{ if () try { } catch (...)} B : : ~B { }"), InternalError);
} }
void garbageCode162() {
//7208
ASSERT_THROW(checkCode("return << >> x return << >> x ", "test.c"), InternalError);
}
}; };
REGISTER_TEST(TestGarbage) REGISTER_TEST(TestGarbage)