#6726 cppcheck hangs with 100% CPU load (invalidcode) inside Token::astOperand2(). #6840 egmentation fault (invalid code) in Token::astOperand2. Improve stability on invalid code
This commit is contained in:
parent
b30d9ffe98
commit
b604d63dd8
|
@ -1099,13 +1099,14 @@ std::string Token::stringifyList(bool varid) const
|
||||||
|
|
||||||
void Token::astOperand1(Token *tok)
|
void Token::astOperand1(Token *tok)
|
||||||
{
|
{
|
||||||
|
const Token* const root = tok;
|
||||||
if (_astOperand1)
|
if (_astOperand1)
|
||||||
_astOperand1->_astParent = nullptr;
|
_astOperand1->_astParent = nullptr;
|
||||||
// goto parent operator
|
// goto parent operator
|
||||||
if (tok) {
|
if (tok) {
|
||||||
while (tok->_astParent) {
|
while (tok->_astParent) {
|
||||||
if (tok->_astParent == this) // #6838 avoid hang on garbage code
|
if (tok->_astParent == this || tok->_astParent == root) // #6838/#6726 avoid hang on garbage code
|
||||||
throw InternalError(this, "Internal error. oken::astOperand1() recursive dependency.");
|
throw InternalError(this, "Internal error. Token::astOperand1() cyclic dependency.");
|
||||||
tok = tok->_astParent;
|
tok = tok->_astParent;
|
||||||
}
|
}
|
||||||
tok->_astParent = this;
|
tok->_astParent = this;
|
||||||
|
@ -1115,13 +1116,15 @@ void Token::astOperand1(Token *tok)
|
||||||
|
|
||||||
void Token::astOperand2(Token *tok)
|
void Token::astOperand2(Token *tok)
|
||||||
{
|
{
|
||||||
|
const Token* const root = tok;
|
||||||
if (_astOperand2)
|
if (_astOperand2)
|
||||||
_astOperand2->_astParent = nullptr;
|
_astOperand2->_astParent = nullptr;
|
||||||
// goto parent operator
|
// goto parent operator
|
||||||
if (tok) {
|
if (tok) {
|
||||||
while (tok->_astParent) {
|
while (tok->_astParent) {
|
||||||
if (tok->_astParent == this) // #6838 avoid hang on garbage code
|
//std::cout << tok << " -> " << tok->_astParent ;
|
||||||
throw InternalError(this, "Internal error. oken::astOperand1() recursive dependency.");
|
if (tok->_astParent == this || tok->_astParent == root) // #6838/#6726 avoid hang on garbage code
|
||||||
|
throw InternalError(this, "Internal error. Token::astOperand2() cyclic dependency.");
|
||||||
tok = tok->_astParent;
|
tok = tok->_astParent;
|
||||||
}
|
}
|
||||||
tok->_astParent = this;
|
tok->_astParent = this;
|
||||||
|
|
|
@ -605,7 +605,7 @@ static void valueFlowBeforeCondition(TokenList *tokenlist, SymbolDatabase *symbo
|
||||||
|
|
||||||
// Variable changed in 3rd for-expression
|
// Variable changed in 3rd for-expression
|
||||||
if (Token::simpleMatch(tok2->previous(), "for (")) {
|
if (Token::simpleMatch(tok2->previous(), "for (")) {
|
||||||
if (isVariableChanged(tok2->astOperand2()->astOperand2(), tok2->link(), varid)) {
|
if (tok2->astOperand2() && isVariableChanged(tok2->astOperand2()->astOperand2(), tok2->link(), varid)) {
|
||||||
varid = 0U;
|
varid = 0U;
|
||||||
if (settings->debugwarnings)
|
if (settings->debugwarnings)
|
||||||
bailout(tokenlist, errorLogger, tok, "variable " + var->name() + " used in loop");
|
bailout(tokenlist, errorLogger, tok, "variable " + var->name() + " used in loop");
|
||||||
|
|
|
@ -138,6 +138,8 @@ private:
|
||||||
TEST_CASE(garbageCode96);
|
TEST_CASE(garbageCode96);
|
||||||
TEST_CASE(garbageCode97);
|
TEST_CASE(garbageCode97);
|
||||||
TEST_CASE(garbageCode98);
|
TEST_CASE(garbageCode98);
|
||||||
|
TEST_CASE(garbageCode99);
|
||||||
|
TEST_CASE(garbageCode100);
|
||||||
|
|
||||||
TEST_CASE(garbageValueFlow);
|
TEST_CASE(garbageValueFlow);
|
||||||
TEST_CASE(garbageSymbolDatabase);
|
TEST_CASE(garbageSymbolDatabase);
|
||||||
|
@ -768,6 +770,17 @@ private:
|
||||||
"fon *tok = f);.s(Token i = d-)L;"), InternalError);
|
"fon *tok = f);.s(Token i = d-)L;"), InternalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void garbageCode99() { // #6726
|
||||||
|
ASSERT_THROW(checkCode("{ xs :: i(:) ! ! x/5 ! !\n"
|
||||||
|
"i, :: a :: b integer, } foo2(x) :: j(:) \n"
|
||||||
|
"b type(*), d(:), a x :: end d(..), foo end\n"
|
||||||
|
"foo4 b d(..), a a x type(*), b foo2 b"), InternalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
void garbageCode100() { // #6840
|
||||||
|
checkCode("( ) { ( i< ) } int foo ( ) { int i ; ( for ( i => 1 ) ; ) }");
|
||||||
|
}
|
||||||
|
|
||||||
void garbageValueFlow() {
|
void garbageValueFlow() {
|
||||||
// #6089
|
// #6089
|
||||||
const char* code = "{} int foo(struct, x1, struct x2, x3, int, x5, x6, x7)\n"
|
const char* code = "{} int foo(struct, x1, struct x2, x3, int, x5, x6, x7)\n"
|
||||||
|
|
Loading…
Reference in New Issue