Fix 10621: FP arrayIndexOutOfBoundsCond with multiple index checks (#3597)

* Fix 10621: FP arrayIndexOutOfBoundsCond with multiple index checks

* Format
This commit is contained in:
Paul Fultz II 2021-12-04 01:54:04 -06:00 committed by GitHub
parent 19006ab775
commit a0d633945e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 3 deletions

View File

@ -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<const Token*> 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<ValueFlow::Value> 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<ValueFlow::Value> isOutOfBoundsImpl(const ValueFlow::Value& s
std::vector<ValueFlow::Value> 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<ValueFlow::Value> result = isOutOfBoundsImpl(size, indexTok, false);
if (!result.empty())
return result;

View File

@ -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"