Skip to content

Commit a0d6339

Browse files
authored
Fix 10621: FP arrayIndexOutOfBoundsCond with multiple index checks (#3597)
* Fix 10621: FP arrayIndexOutOfBoundsCond with multiple index checks * Format
1 parent 19006ab commit a0d6339

2 files changed

Lines changed: 35 additions & 3 deletions

File tree

lib/valueflow.cpp

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,24 @@ static void setTokenValue(Token* tok, ValueFlow::Value value, const Settings* se
897897
else if (Token::Match(parent, ":: %name%") && parent->astOperand2() == tok) {
898898
setTokenValue(parent, value, settings);
899899
}
900+
// Calling std::size or std::empty on an array
901+
else if (value.isTokValue() && Token::simpleMatch(value.tokvalue, "{") && tok->variable() &&
902+
tok->variable()->isArray() && Token::Match(parent->previous(), "%name% (") && astIsRHS(tok)) {
903+
std::vector<const Token*> args = getArguments(value.tokvalue);
904+
if (const Library::Function* f = settings->library.getFunction(parent->previous())) {
905+
if (f->containerYield == Library::Container::Yield::SIZE) {
906+
ValueFlow::Value v(value);
907+
v.valueType = ValueFlow::Value::ValueType::INT;
908+
v.intvalue = args.size();
909+
setTokenValue(parent, v, settings);
910+
} else if (f->containerYield == Library::Container::Yield::EMPTY) {
911+
ValueFlow::Value v(value);
912+
v.intvalue = args.empty();
913+
v.valueType = ValueFlow::Value::ValueType::INT;
914+
setTokenValue(parent, v, settings);
915+
}
916+
}
917+
}
900918
}
901919

902920
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
78407858
return {};
78417859
if (size.bound == ValueFlow::Value::Bound::Lower)
78427860
return {};
7843-
ValueFlow::Value inBoundsValue = inferCondition("<", indexTok, size.intvalue);
7844-
if (inBoundsValue.isKnown() && inBoundsValue.intvalue != 0)
7845-
return {};
78467861
ValueFlow::Value value = inferCondition(">=", indexTok, indexValue->intvalue);
78477862
if (!value.isKnown())
78487863
return {};
@@ -7855,6 +7870,9 @@ static std::vector<ValueFlow::Value> isOutOfBoundsImpl(const ValueFlow::Value& s
78557870

78567871
std::vector<ValueFlow::Value> ValueFlow::isOutOfBounds(const Value& size, const Token* indexTok, bool possible)
78577872
{
7873+
ValueFlow::Value inBoundsValue = inferCondition("<", indexTok, size.intvalue);
7874+
if (inBoundsValue.isKnown() && inBoundsValue.intvalue != 0)
7875+
return {};
78587876
std::vector<ValueFlow::Value> result = isOutOfBoundsImpl(size, indexTok, false);
78597877
if (!result.empty())
78607878
return result;

test/testbufferoverrun.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ class TestBufferOverrun : public TestFixture {
178178
TEST_CASE(array_index_58); // #7524
179179
TEST_CASE(array_index_59); // #10413
180180
TEST_CASE(array_index_60); // #10617, #9824
181+
TEST_CASE(array_index_61); // #10621
181182
TEST_CASE(array_index_multidim);
182183
TEST_CASE(array_index_switch_in_for);
183184
TEST_CASE(array_index_for_in_for); // FP: #2634
@@ -1730,6 +1731,19 @@ class TestBufferOverrun : public TestFixture {
17301731
errout.str());
17311732
}
17321733

1734+
void array_index_61()
1735+
{
1736+
check("int f(int i) {\n"
1737+
" const int M[] = { 0, 1, 2, 3 };\n"
1738+
" if (i > 4)\n"
1739+
" return -1;\n"
1740+
" if (i < 0 || i == std::size(M))\n"
1741+
" return 0; \n"
1742+
" return M[i];\n"
1743+
"}\n");
1744+
ASSERT_EQUALS("", errout.str());
1745+
}
1746+
17331747
void array_index_multidim() {
17341748
check("void f()\n"
17351749
"{\n"

0 commit comments

Comments
 (0)