diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index a57dfc9d0..438b5a115 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -31,6 +31,7 @@ #include #include // <- assert #include +#include //--------------------------------------------------------------------------- @@ -978,6 +979,32 @@ void CheckBufferOverrun::checkScope(const Token *tok, const ArrayInfo &arrayInfo // Negative size in array declarations //--------------------------------------------------------------------------- +static bool isVLAIndex(const Token *index) +{ + std::stack tokens; + tokens.push(index); + while (!tokens.empty()) { + const Token *tok = tokens.top(); + tokens.pop(); + if (!tok) + continue; + if (tok->varId() != 0U) + return true; + if (tok->str() == "?") { + // this is a VLA index if both expressions around the ":" is VLA index + if (tok->astOperand2() && + tok->astOperand2()->str() == ":" && + isVLAIndex(tok->astOperand2()->astOperand1()) && + isVLAIndex(tok->astOperand2()->astOperand2())) + return true; + continue; + } + tokens.push(tok->astOperand1()); + tokens.push(tok->astOperand2()); + } + return false; +} + void CheckBufferOverrun::negativeArraySize() { const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase(); @@ -989,9 +1016,9 @@ void CheckBufferOverrun::negativeArraySize() if (!Token::Match(nameToken, "%var% [") || !nameToken->next()->astOperand2()) continue; const ValueFlow::Value *sz = nameToken->next()->astOperand2()->getValueLE(-1,_settings); - if (!sz) - continue; - negativeArraySizeError(nameToken); + // don't warn about constant negative index because that is a compiler error + if (sz && isVLAIndex(nameToken->next()->astOperand2())) + negativeArraySizeError(nameToken); } } diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index 7f984cb62..1e4cda696 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -3820,6 +3820,13 @@ private: "}\n" "void x() { f(-100); }"); ASSERT_EQUALS("[test.cpp:2]: (error) Declaration of array 'a' with negative size is undefined behaviour\n", errout.str()); + + // don't warn for constant sizes -> this is a compiler error so this is used for static assertions for instance + check("int x, y;\n" + "int a[-1];\n" + "int b[x?1:-1];\n" + "int c[x?y:-1];\n"); + ASSERT_EQUALS("", errout.str()); } void garbage1() {