Fix 10726: Crash in CheckExceptionSafety::checkRethrowCopy (#3711)

This commit is contained in:
Paul Fultz II 2022-01-16 05:35:51 -06:00 committed by GitHub
parent 89bc226738
commit abb0563cef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 91 additions and 16 deletions

View File

@ -4824,8 +4824,6 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
// Simplify the C alternative tokens (and, or, etc.) // Simplify the C alternative tokens (and, or, etc.)
simplifyCAlternativeTokens(); simplifyCAlternativeTokens();
reportUnknownMacros();
simplifyFunctionTryCatch(); simplifyFunctionTryCatch();
simplifyHeadersAndUnusedTemplates(); simplifyHeadersAndUnusedTemplates();
@ -5020,6 +5018,8 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
// Split up variable declarations. // Split up variable declarations.
simplifyVarDecl(false); simplifyVarDecl(false);
reportUnknownMacros();
// typedef.. // typedef..
if (mTimerResults) { if (mTimerResults) {
Timer t("Tokenizer::tokenize::simplifyTypedef", mSettings->showtime, mTimerResults); Timer t("Tokenizer::tokenize::simplifyTypedef", mSettings->showtime, mTimerResults);
@ -10068,6 +10068,17 @@ static const Token* skipCPPOrAlignAttribute(const Token * tok)
return tok; return tok;
} }
static bool isNonMacro(const Token* tok)
{
if (tok->isKeyword())
return true;
if (cAlternativeTokens.count(tok->str()) > 0)
return true;
if (tok->str().compare(0, 2, "__") == 0) // attribute/annotation
return true;
return false;
}
void Tokenizer::reportUnknownMacros() const void Tokenizer::reportUnknownMacros() const
{ {
// Report unknown macros used in expressions "%name% %num%" // Report unknown macros used in expressions "%name% %num%"
@ -10161,6 +10172,29 @@ void Tokenizer::reportUnknownMacros() const
unknownMacroError(tok->next()); unknownMacroError(tok->next());
} }
} }
// Report unknown macros without commas or operators inbetween statements: MACRO1() MACRO2()
for (const Token* tok = tokens(); tok; tok = tok->next()) {
if (!Token::Match(tok, "%name% ("))
continue;
if (isNonMacro(tok))
continue;
const Token* endTok = tok->linkAt(1);
if (!Token::Match(endTok, ") %name% (|."))
continue;
const Token* tok2 = endTok->next();
if (isNonMacro(tok2))
continue;
if (tok2->next()->str() == "(") {
if (Token::Match(tok->previous(), "%name%|::|>"))
continue;
}
unknownMacroError(tok);
}
} }
void Tokenizer::findGarbageCode() const void Tokenizer::findGarbageCode() const

View File

@ -135,14 +135,17 @@ void TokenList::determineCppC()
mKeywords.insert("mutable"); mKeywords.insert("mutable");
mKeywords.insert("namespace"); mKeywords.insert("namespace");
mKeywords.insert("new"); mKeywords.insert("new");
mKeywords.insert("noexcept");
mKeywords.insert("operator"); mKeywords.insert("operator");
mKeywords.insert("private"); mKeywords.insert("private");
mKeywords.insert("protected"); mKeywords.insert("protected");
mKeywords.insert("public"); mKeywords.insert("public");
mKeywords.insert("reinterpret_cast"); mKeywords.insert("reinterpret_cast");
mKeywords.insert("static_assert");
mKeywords.insert("static_cast"); mKeywords.insert("static_cast");
mKeywords.insert("template"); mKeywords.insert("template");
mKeywords.insert("this"); mKeywords.insert("this");
mKeywords.insert("thread_local");
mKeywords.insert("throw"); mKeywords.insert("throw");
//mKeywords.insert("true"); // literal //mKeywords.insert("true"); // literal
mKeywords.insert("try"); mKeywords.insert("try");
@ -152,6 +155,19 @@ void TokenList::determineCppC()
mKeywords.insert("using"); mKeywords.insert("using");
mKeywords.insert("virtual"); mKeywords.insert("virtual");
//mKeywords.insert("wchar_t"); // type //mKeywords.insert("wchar_t"); // type
if (!mSettings || mSettings->standards.cpp >= Standards::CPP20) {
mKeywords.insert("alignas");
mKeywords.insert("alignof");
mKeywords.insert("axiom");
mKeywords.insert("co_await");
mKeywords.insert("co_return");
mKeywords.insert("co_yield");
mKeywords.insert("concept");
mKeywords.insert("synchronized");
mKeywords.insert("consteval");
mKeywords.insert("reflexpr");
mKeywords.insert("requires");
}
} }
} }
@ -613,7 +629,8 @@ static bool iscpp11init_impl(const Token * const tok)
nameToken = nameToken->link()->previous(); nameToken = nameToken->link()->previous();
const Token *endtok = nullptr; const Token *endtok = nullptr;
if (Token::Match(nameToken, "%name%|return {") && (!Token::simpleMatch(nameToken->tokAt(2), "[") || findLambdaEndScope(nameToken->tokAt(2)))) if (Token::Match(nameToken, "%name%|return|: {") &&
(!Token::simpleMatch(nameToken->tokAt(2), "[") || findLambdaEndScope(nameToken->tokAt(2))))
endtok = nameToken->linkAt(1); endtok = nameToken->linkAt(1);
else if (Token::Match(nameToken,"%name% <") && Token::simpleMatch(nameToken->linkAt(1),"> {")) else if (Token::Match(nameToken,"%name% <") && Token::simpleMatch(nameToken->linkAt(1),"> {"))
endtok = nameToken->linkAt(1)->linkAt(1); endtok = nameToken->linkAt(1)->linkAt(1);
@ -625,7 +642,7 @@ static bool iscpp11init_impl(const Token * const tok)
return false; return false;
if (Token::simpleMatch(nameToken->previous(), "namespace")) if (Token::simpleMatch(nameToken->previous(), "namespace"))
return false; return false;
if (Token::Match(nameToken, "%any% {")) { if (Token::Match(nameToken, "%any% {") && !Token::Match(nameToken, "return|:")) {
// If there is semicolon between {..} this is not a initlist // If there is semicolon between {..} this is not a initlist
for (const Token *tok2 = nameToken->next(); tok2 != endtok; tok2 = tok2->next()) { for (const Token *tok2 = nameToken->next(); tok2 != endtok; tok2 = tok2->next()) {
if (tok2->str() == ";") if (tok2->str() == ";")
@ -819,7 +836,7 @@ static void compileTerm(Token *&tok, AST_state& state)
} }
} else } else
compileBinOp(tok, state, compileExpression); compileBinOp(tok, state, compileExpression);
if (Token::Match(tok, "} ,|:")) if (Token::Match(tok, "} ,|:|)"))
tok = tok->next(); tok = tok->next();
} else if (state.cpp && Token::Match(tok->tokAt(-2), "%name% ( {") && !Token::findsimplematch(tok, ";", tok->link())) { } else if (state.cpp && Token::Match(tok->tokAt(-2), "%name% ( {") && !Token::findsimplematch(tok, ";", tok->link())) {
if (Token::simpleMatch(tok, "{ }")) if (Token::simpleMatch(tok, "{ }"))
@ -1678,6 +1695,20 @@ void TokenList::validateAst() const
"' doesn't have two operands.", "' doesn't have two operands.",
InternalError::AST); InternalError::AST);
} }
// Check member access
if (Token::Match(tok, "%var% .")) {
if (!tok->astParent()) {
throw InternalError(
tok, "Syntax Error: AST broken, '" + tok->str() + "' doesn't have a parent.", InternalError::AST);
}
if (!tok->next()->astOperand1() || !tok->next()->astOperand2()) {
const std::string& op =
tok->next()->originalName().empty() ? tok->next()->str() : tok->next()->originalName();
throw InternalError(
tok, "Syntax Error: AST broken, '" + op + "' doesn't have two operands.", InternalError::AST);
}
}
} }
} }

View File

@ -212,7 +212,7 @@ void validCode()
PSID pEveryoneSID = NULL; PSID pEveryoneSID = NULL;
SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID) AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID);
FreeSid(pEveryoneSID); FreeSid(pEveryoneSID);
LPVOID pMem = HeapAlloc(GetProcessHeap(), 0, 10); LPVOID pMem = HeapAlloc(GetProcessHeap(), 0, 10);
@ -629,7 +629,7 @@ void ignoredReturnValue()
GetLastError(); GetLastError();
// cppcheck-suppress ignoredReturnValue // cppcheck-suppress ignoredReturnValue
GetProcessHeap() GetProcessHeap();
// cppcheck-suppress ignoredReturnValue // cppcheck-suppress ignoredReturnValue
// cppcheck-suppress leakReturnValNotUsed // cppcheck-suppress leakReturnValNotUsed
HeapAlloc(GetProcessHeap(), 0, 10); HeapAlloc(GetProcessHeap(), 0, 10);

View File

@ -4626,9 +4626,12 @@ private:
check("void f() {\n" check("void f() {\n"
" char str[8];\n" " char str[8];\n"
" scanf_s(\"%8c\", str, sizeof(str))\n" " scanf_s(\"%8c\", str, sizeof(str));\n"
" scanf_s(\"%9c\", str, sizeof(str))\n" " scanf_s(\"%9c\", str, sizeof(str));\n"
"}\n", false, false, Settings::Win32A); "}\n",
false,
false,
Settings::Win32A);
ASSERT_EQUALS("[test.cpp:4]: (error) Width 9 given in format string (no. 1) is larger than destination buffer 'str[8]', use %8c to prevent overflowing it.\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Width 9 given in format string (no. 1) is larger than destination buffer 'str[8]', use %8c to prevent overflowing it.\n", errout.str());
check("void foo() {\n" check("void foo() {\n"

View File

@ -1658,12 +1658,12 @@ private:
"std::vector<int>& g();\n" "std::vector<int>& g();\n"
"void foo() {\n" "void foo() {\n"
" auto it = f().end() - 1;\n" " auto it = f().end() - 1;\n"
" f().begin() - it\n" " f().begin() - it;\n"
" f().begin()+1 - it\n" " f().begin()+1 - it;\n"
" f().begin() - (it + 1)\n" " f().begin() - (it + 1);\n"
" f().begin() - f().end()\n" " f().begin() - f().end();\n"
" f().begin()+1 - f().end()\n" " f().begin()+1 - f().end();\n"
" f().begin() - (f().end() + 1)\n" " f().begin() - (f().end() + 1);\n"
" (void)std::find(f().begin(), it, 0);\n" " (void)std::find(f().begin(), it, 0);\n"
" (void)std::find(f().begin(), it + 1, 0);\n" " (void)std::find(f().begin(), it + 1, 0);\n"
" (void)std::find(f().begin() + 1, it + 1, 0);\n" " (void)std::find(f().begin() + 1, it + 1, 0);\n"

View File

@ -5905,6 +5905,7 @@ private:
ASSERT_EQUALS("foryz:(", testAst("for (decltype(x) *y : z);")); ASSERT_EQUALS("foryz:(", testAst("for (decltype(x) *y : z);"));
ASSERT_EQUALS("for(tmpNULL!=tmptmpnext.=;;( tmpa=", testAst("for ( ({ tmp = a; }) ; tmp != NULL; tmp = tmp->next ) {}")); ASSERT_EQUALS("for(tmpNULL!=tmptmpnext.=;;( tmpa=", testAst("for ( ({ tmp = a; }) ; tmp != NULL; tmp = tmp->next ) {}"));
ASSERT_EQUALS("forx0=x;;(", testAst("for (int x=0; x;);")); ASSERT_EQUALS("forx0=x;;(", testAst("for (int x=0; x;);"));
ASSERT_EQUALS("forae*bc.({:(", testAst("for (a *e : {b->c()});"));
// for with initializer (c++20) // for with initializer (c++20)
ASSERT_EQUALS("forab=ca:;(", testAst("for(a=b;int c:a)")); ASSERT_EQUALS("forab=ca:;(", testAst("for(a=b;int c:a)"));
@ -6500,6 +6501,12 @@ private:
const char code8[] = "void foo() { a = [](int x, decltype(vec) y){}; }"; const char code8[] = "void foo() { a = [](int x, decltype(vec) y){}; }";
ASSERT_NO_THROW(tokenizeAndStringify(code8)); ASSERT_NO_THROW(tokenizeAndStringify(code8));
const char code9[] = "void f(std::exception c) { b(M() c.what()); }";
ASSERT_THROW(tokenizeAndStringify(code9), InternalError);
const char code10[] = "void f(std::exception c) { b(M() M() + N(c.what())); }";
ASSERT_THROW(tokenizeAndStringify(code10), InternalError);
} }
void findGarbageCode() { // Test Tokenizer::findGarbageCode() void findGarbageCode() { // Test Tokenizer::findGarbageCode()