Fix 10726: Crash in CheckExceptionSafety::checkRethrowCopy (#3711)
This commit is contained in:
parent
89bc226738
commit
abb0563cef
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in New Issue