diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index d839c4daa..dbed0639f 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1206,7 +1206,7 @@ static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, b const Token *tok2 = tok->tokAt(2); // skip over tokens to find variable or type - while (Token::Match(tok2, "%name% ::|.|[")) { + while (tok2 && !tok2->isStandardType() && Token::Match(tok2, "%name% ::|.|[")) { if (tok2->next()->str() == "[") tok2 = tok2->linkAt(1)->next(); else @@ -1322,8 +1322,25 @@ static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, b setTokenValue(tok->next(), value, settings); } } else if (!tok2->type()) { - const ValueType &vt = ValueType::parseDecl(tok2,settings); - const size_t sz = ValueFlow::getSizeOf(vt, settings); + const ValueType& vt = ValueType::parseDecl(tok2, settings); + size_t sz = ValueFlow::getSizeOf(vt, settings); + const Token* brac = tok2->astParent(); + while (Token::simpleMatch(brac, "[")) { + const Token* num = brac->astOperand2(); + if (num && ((num->isNumber() && MathLib::isInt(num->str())) || num->tokType() == Token::eChar)) { + try { + MathLib::biguint dim = MathLib::toULongNumber(num->str()); + sz *= dim; + brac = brac->astParent(); + continue; + } + catch (const std::exception& /*e*/) { + // Bad integer literal + } + } + sz = 0; + break; + } if (sz > 0) { ValueFlow::Value value(sz); if (!tok2->isTemplateArg() && settings->platformType != cppcheck::Platform::Unspecified) diff --git a/test/testother.cpp b/test/testother.cpp index ed3ed8547..32c86d81b 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -66,6 +66,7 @@ private: TEST_CASE(zeroDiv14); // #1169 TEST_CASE(zeroDiv15); // #8319 TEST_CASE(zeroDiv16); // #11158 + TEST_CASE(zeroDiv17); // #9931 TEST_CASE(zeroDivCond); // division by zero / useless condition @@ -637,6 +638,15 @@ private: ASSERT_EQUALS("", errout.str()); } + void zeroDiv17() { // #9931 + check("int f(int len) {\n" + " int sz = sizeof(void*[255]) / 255;\n" + " int x = len % sz;\n" + " return x;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + } + void zeroDivCond() { check("void f(unsigned int x) {\n" " int y = 17 / x;\n" diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index f60a12b90..1c7c8cc4d 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -1343,6 +1343,11 @@ private: values = tokenValues(code,"( arr )"); ASSERT_EQUALS(1U, values.size()); ASSERT_EQUALS(10 * sizeof(std::uint16_t), values.back().intvalue); + + code = "int sz = sizeof(int32_t[10][20]);"; + values = tokenValues(code, "="); + ASSERT_EQUALS(1U, values.size()); + ASSERT_EQUALS(sizeof(std::int32_t) * 10 * 20, values.back().intvalue); } void valueFlowErrorPath() {