Fix #10809 cppcheckError Cyclic reverse analysis (#5137)

* Fix #10809 cppcheckError Cyclic reverse analysis

* Handle fixed AST in ValueFlow, fix FN

* Remove
This commit is contained in:
chrchr-github 2023-06-10 07:41:52 +02:00 committed by GitHub
parent 69116c8386
commit d4705ca8ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 25 additions and 11 deletions

View File

@ -560,9 +560,9 @@ static bool iscpp11init_impl(const Token * const tok)
return true;
if (nameToken->str() == ">" && nameToken->link())
nameToken = nameToken->link()->previous();
if (nameToken->str() == "]") {
const Token* newTok = nameToken->link()->previous();
while (Token::Match(newTok, "%type%|::") && !newTok->isKeyword())
if (Token::Match(nameToken, "]|*")) {
const Token* newTok = nameToken->link() ? nameToken->link()->previous() : nameToken->previous();
while (Token::Match(newTok, "%type%|::|*") && !newTok->isKeyword())
newTok = newTok->previous();
if (Token::simpleMatch(newTok, "new"))
return true;
@ -880,8 +880,10 @@ static void compilePrecedence2(Token *&tok, AST_state& state)
{
auto doCompileScope = [&](const Token* tok) -> bool {
const bool isStartOfCpp11Init = state.cpp && tok && tok->str() == "{" && iscpp11init(tok);
if (isStartOfCpp11Init) {
if (isStartOfCpp11Init || Token::simpleMatch(tok, "(")) {
tok = tok->previous();
while (Token::simpleMatch(tok, "*"))
tok = tok->previous();
while (tok && Token::Match(tok->previous(), ":: %type%"))
tok = tok->tokAt(-2);
if (tok && !tok->isKeyword())
@ -891,8 +893,11 @@ static void compilePrecedence2(Token *&tok, AST_state& state)
return !findLambdaEndTokenWithoutAST(tok);
};
if (doCompileScope(tok))
bool isNew = true;
if (doCompileScope(tok)) {
compileScope(tok, state);
isNew = false;
}
while (tok) {
if (tok->tokType() == Token::eIncDecOp && !isPrefixUnary(tok, state.cpp)) {
compileUnaryOp(tok, state, compileScope);
@ -982,7 +987,7 @@ static void compilePrecedence2(Token *&tok, AST_state& state)
const std::size_t oldOpSize = state.op.size();
compileExpression(tok, state);
tok = tok2;
if ((oldOpSize > 0 && Token::simpleMatch(tok->previous(), "} ("))
if ((oldOpSize > 0 && (isNew || Token::simpleMatch(tok->previous(), "} (")))
|| (tok->previous() && tok->previous()->isName() && !Token::Match(tok->previous(), "return|case") && (!state.cpp || !Token::Match(tok->previous(), "throw|delete")))
|| (tok->strAt(-1) == "]" && (!state.cpp || !Token::Match(tok->linkAt(-1)->previous(), "new|delete")))
|| (tok->strAt(-1) == ">" && tok->linkAt(-1))

View File

@ -8941,17 +8941,14 @@ static void valueFlowDynamicBufferSize(const TokenList* tokenlist, const SymbolD
const Token* bracTok = nullptr, *typeTok = nullptr;
if (newTok->astOperand1()->str() == "[")
bracTok = newTok->astOperand1();
else if (newTok->astOperand1()->str() == "(") {
else if (Token::Match(newTok->astOperand1(), "(|{")) {
if (newTok->astOperand1()->astOperand1() && newTok->astOperand1()->astOperand1()->str() == "[")
bracTok = newTok->astOperand1()->astOperand1();
else
typeTok = newTok->astOperand1()->astOperand1();
}
else {
else
typeTok = newTok->astOperand1();
if (typeTok->str() == "{")
typeTok = typeTok->astOperand1();
}
if (bracTok && bracTok->astOperand2() && bracTok->astOperand2()->hasKnownIntValue())
numElem = bracTok->astOperand2()->getKnownIntValue();
else if (Token::Match(typeTok, "%type%"))

View File

@ -2880,6 +2880,14 @@ private:
" delete[] z;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Array 'z[5]' accessed at index 7, which is out of bounds.\n", errout.str());
check("void h() {\n"
" int** z = new int* [5]{ 0 };\n"
" for (int n = 0; n < 8; ++n)\n"
" z[n] = nullptr;\n"
" delete[] z;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Array 'z[5]' accessed at index 7, which is out of bounds.\n", errout.str());
}
void buffer_overrun_2_struct() {

View File

@ -6178,6 +6178,10 @@ private:
ASSERT_EQUALS("intnewdelete", testAst("void f() { delete new int; }"));
ASSERT_EQUALS("pint3[new1+=", testAst("p = (new int[3]) + 1;")); // #11327
ASSERT_EQUALS("aType2[T1T2,{new=", testAst("a = new Type *[2] {T1, T2};")); // #11745
ASSERT_EQUALS("pSthis(new=", testAst("p = new S*(this);")); // #10809
ASSERT_EQUALS("pint0{new=", testAst("p = new int*{ 0 };"));
ASSERT_EQUALS("pint5[{new=", testAst("p = new int* [5]{};"));
ASSERT_EQUALS("pint5[0{new=", testAst("p = new int* [5]{ 0 };"));
// placement new
ASSERT_EQUALS("X12,3,(new ab,c,", testAst("new (a,b,c) X(1,2,3);"));