diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index bf35c4b1b..788a20bb7 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -897,6 +897,24 @@ static void setTokenValue(Token* tok, ValueFlow::Value value, const Settings* se else if (Token::Match(parent, ":: %name%") && parent->astOperand2() == tok) { setTokenValue(parent, value, settings); } + // Calling std::size or std::empty on an array + else if (value.isTokValue() && Token::simpleMatch(value.tokvalue, "{") && tok->variable() && + tok->variable()->isArray() && Token::Match(parent->previous(), "%name% (") && astIsRHS(tok)) { + std::vector args = getArguments(value.tokvalue); + if (const Library::Function* f = settings->library.getFunction(parent->previous())) { + if (f->containerYield == Library::Container::Yield::SIZE) { + ValueFlow::Value v(value); + v.valueType = ValueFlow::Value::ValueType::INT; + v.intvalue = args.size(); + setTokenValue(parent, v, settings); + } else if (f->containerYield == Library::Container::Yield::EMPTY) { + ValueFlow::Value v(value); + v.intvalue = args.empty(); + v.valueType = ValueFlow::Value::ValueType::INT; + setTokenValue(parent, v, settings); + } + } + } } static void setTokenValueCast(Token *parent, const ValueType &valueType, const ValueFlow::Value &value, const Settings *settings) @@ -7840,9 +7858,6 @@ static std::vector isOutOfBoundsImpl(const ValueFlow::Value& s return {}; if (size.bound == ValueFlow::Value::Bound::Lower) return {}; - ValueFlow::Value inBoundsValue = inferCondition("<", indexTok, size.intvalue); - if (inBoundsValue.isKnown() && inBoundsValue.intvalue != 0) - return {}; ValueFlow::Value value = inferCondition(">=", indexTok, indexValue->intvalue); if (!value.isKnown()) return {}; @@ -7855,6 +7870,9 @@ static std::vector isOutOfBoundsImpl(const ValueFlow::Value& s std::vector ValueFlow::isOutOfBounds(const Value& size, const Token* indexTok, bool possible) { + ValueFlow::Value inBoundsValue = inferCondition("<", indexTok, size.intvalue); + if (inBoundsValue.isKnown() && inBoundsValue.intvalue != 0) + return {}; std::vector result = isOutOfBoundsImpl(size, indexTok, false); if (!result.empty()) return result; diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index c1361812f..f421cabeb 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -178,6 +178,7 @@ private: TEST_CASE(array_index_58); // #7524 TEST_CASE(array_index_59); // #10413 TEST_CASE(array_index_60); // #10617, #9824 + TEST_CASE(array_index_61); // #10621 TEST_CASE(array_index_multidim); TEST_CASE(array_index_switch_in_for); TEST_CASE(array_index_for_in_for); // FP: #2634 @@ -1730,6 +1731,19 @@ private: errout.str()); } + void array_index_61() + { + check("int f(int i) {\n" + " const int M[] = { 0, 1, 2, 3 };\n" + " if (i > 4)\n" + " return -1;\n" + " if (i < 0 || i == std::size(M))\n" + " return 0; \n" + " return M[i];\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + } + void array_index_multidim() { check("void f()\n" "{\n"