diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index dbc41f16a..4c2cc0cf8 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -1120,33 +1120,37 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int // goto the { tok = tok->next()->link()->next(); - bool possibleInitIf(number_of_if > 0 || suppressErrors); - const bool initif = checkScopeForVariable(tok->next(), varid, ispointer, &possibleInitIf); - - // goto the } - tok = tok->link(); - - if (!Token::simpleMatch(tok, "} else {")) { - if (initif || possibleInitIf) { - ++number_of_if; - if (number_of_if >= 2) - return true; - } - } else { - // goto the { - tok = tok->tokAt(2); - - bool possibleInitElse(number_of_if > 0 || suppressErrors); - const bool initelse = checkScopeForVariable(tok->next(), varid, ispointer, &possibleInitElse); + if (!tok) + break; + if (tok->str() == "{") { + bool possibleInitIf(number_of_if > 0 || suppressErrors); + const bool initif = checkScopeForVariable(tok->next(), varid, ispointer, &possibleInitIf); // goto the } tok = tok->link(); - if (initif && initelse) - return true; + if (!Token::simpleMatch(tok, "} else {")) { + if (initif || possibleInitIf) { + ++number_of_if; + if (number_of_if >= 2) + return true; + } + } else { + // goto the { + tok = tok->tokAt(2); - if (initif || initelse || possibleInitElse) - ++number_of_if; + bool possibleInitElse(number_of_if > 0 || suppressErrors); + const bool initelse = checkScopeForVariable(tok->next(), varid, ispointer, &possibleInitElse); + + // goto the } + tok = tok->link(); + + if (initif && initelse) + return true; + + if (initif || initelse || possibleInitElse) + ++number_of_if; + } } } @@ -1177,16 +1181,18 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int // goto the { const Token *tok2 = tok->next()->link()->next(); - bool possibleinit = true; - bool init = checkScopeForVariable(tok2->next(), varid, ispointer, &possibleinit); + if (tok2 && tok2->str() == "{") { + bool possibleinit = true; + bool init = checkScopeForVariable(tok2->next(), varid, ispointer, &possibleinit); - // variable is initialized in the loop.. - if (possibleinit || init) - return true; + // variable is initialized in the loop.. + if (possibleinit || init) + return true; - // is variable used in for-head? - if (!suppressErrors) { - checkIfForWhileHead(tok->next(), varid, ispointer, false, bool(number_of_if == 0)); + // is variable used in for-head? + if (!suppressErrors) { + checkIfForWhileHead(tok->next(), varid, ispointer, false, bool(number_of_if == 0)); + } } } @@ -1206,7 +1212,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int return true; // variable is seen.. - if (tok->varId() == varid) { + if (tok && tok->varId() == varid) { // Use variable if (!suppressErrors && isVariableUsage(tok, ispointer)) uninitvarError(tok, tok->str()); diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 768201db8..bfa00a366 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -2019,6 +2019,16 @@ private: " typeof(*abc);\n" "}"); ASSERT_EQUALS("", errout.str()); + + // Ticket #3486 - Don't crash garbage code + checkUninitVar2("void f()\n" + "{\n" + " (\n" + " x;\n" + " int a, a2, a2*x; if () ;\n" + " )\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: a2\n", errout.str()); } };