Fix 11844: FP negativeIndex for known loop (#5282)

This commit is contained in:
Paul Fultz II 2023-08-14 08:17:05 -05:00 committed by GitHub
parent c257c70347
commit 8aa9d710d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 45 additions and 7 deletions

View File

@ -900,9 +900,16 @@ bool extractForLoopValues(const Token *forToken,
if (!initExpr || !initExpr->isBinaryOp() || initExpr->str() != "=" || !Token::Match(initExpr->astOperand1(), "%var%")) if (!initExpr || !initExpr->isBinaryOp() || initExpr->str() != "=" || !Token::Match(initExpr->astOperand1(), "%var%"))
return false; return false;
std::vector<MathLib::bigint> minInitValue = getMinValue(ValueFlow::makeIntegralInferModel(), initExpr->astOperand2()->values()); std::vector<MathLib::bigint> minInitValue = getMinValue(ValueFlow::makeIntegralInferModel(), initExpr->astOperand2()->values());
if (minInitValue.empty()) {
const ValueFlow::Value* v = initExpr->astOperand2()->getMinValue(true);
if (v)
minInitValue.push_back(v->intvalue);
}
if (minInitValue.empty())
return false;
varid = initExpr->astOperand1()->varId(); varid = initExpr->astOperand1()->varId();
knownInitValue = initExpr->astOperand2()->hasKnownIntValue(); knownInitValue = initExpr->astOperand2()->hasKnownIntValue();
initValue = minInitValue.empty() ? 0 : minInitValue.front(); initValue = minInitValue.front();
partialCond = Token::Match(condExpr, "%oror%|&&"); partialCond = Token::Match(condExpr, "%oror%|&&");
visitAstNodes(condExpr, [varid, &condExpr](const Token *tok) { visitAstNodes(condExpr, [varid, &condExpr](const Token *tok) {
if (Token::Match(tok, "%oror%|&&")) if (Token::Match(tok, "%oror%|&&"))

View File

@ -2415,25 +2415,40 @@ const ValueFlow::Value* Token::getValue(const MathLib::bigint val) const
return it == mImpl->mValues->end() ? nullptr : &*it; return it == mImpl->mValues->end() ? nullptr : &*it;
} }
const ValueFlow::Value* Token::getMaxValue(bool condition, MathLib::bigint path) const template<class Compare>
static const ValueFlow::Value* getCompareValue(const std::list<ValueFlow::Value>& values,
bool condition,
MathLib::bigint path,
Compare compare)
{ {
if (!mImpl->mValues)
return nullptr;
const ValueFlow::Value* ret = nullptr; const ValueFlow::Value* ret = nullptr;
for (const ValueFlow::Value& value : *mImpl->mValues) { for (const ValueFlow::Value& value : values) {
if (!value.isIntValue()) if (!value.isIntValue())
continue; continue;
if (value.isImpossible()) if (value.isImpossible())
continue; continue;
if (path > -0 && value.path != 0 && value.path != path) if (path > -0 && value.path != 0 && value.path != path)
continue; continue;
if ((!ret || value.intvalue > ret->intvalue) && if ((!ret || compare(value.intvalue, ret->intvalue)) && ((value.condition != nullptr) == condition))
((value.condition != nullptr) == condition))
ret = &value; ret = &value;
} }
return ret; return ret;
} }
const ValueFlow::Value* Token::getMaxValue(bool condition, MathLib::bigint path) const
{
if (!mImpl->mValues)
return nullptr;
return getCompareValue(*mImpl->mValues, condition, path, std::greater<MathLib::bigint>{});
}
const ValueFlow::Value* Token::getMinValue(bool condition, MathLib::bigint path) const
{
if (!mImpl->mValues)
return nullptr;
return getCompareValue(*mImpl->mValues, condition, path, std::less<MathLib::bigint>{});
}
const ValueFlow::Value* Token::getMovedValue() const const ValueFlow::Value* Token::getMovedValue() const
{ {
if (!mImpl->mValues) if (!mImpl->mValues)

View File

@ -1224,6 +1224,7 @@ public:
const ValueFlow::Value* getValue(const MathLib::bigint val) const; const ValueFlow::Value* getValue(const MathLib::bigint val) const;
const ValueFlow::Value* getMaxValue(bool condition, MathLib::bigint path = 0) const; const ValueFlow::Value* getMaxValue(bool condition, MathLib::bigint path = 0) const;
const ValueFlow::Value* getMinValue(bool condition, MathLib::bigint path = 0) const;
const ValueFlow::Value* getMovedValue() const; const ValueFlow::Value* getMovedValue() const;

View File

@ -190,6 +190,7 @@ private:
TEST_CASE(array_index_negative7); // #5685 TEST_CASE(array_index_negative7); // #5685
TEST_CASE(array_index_negative8); // #11651 TEST_CASE(array_index_negative8); // #11651
TEST_CASE(array_index_negative9); TEST_CASE(array_index_negative9);
TEST_CASE(array_index_negative10);
TEST_CASE(array_index_for_decr); TEST_CASE(array_index_for_decr);
TEST_CASE(array_index_varnames); // FP: struct member #1576, FN: #1586 TEST_CASE(array_index_varnames); // FP: struct member #1576, FN: #1586
TEST_CASE(array_index_for_continue); // for,continue TEST_CASE(array_index_for_continue); // for,continue
@ -2336,6 +2337,20 @@ private:
ASSERT_EQUALS("[test.cpp:8]: (error) Array 'a[3]' accessed at index -1, which is out of bounds.\n", errout.str()); ASSERT_EQUALS("[test.cpp:8]: (error) Array 'a[3]' accessed at index -1, which is out of bounds.\n", errout.str());
} }
// #11844
void array_index_negative10()
{
check("struct S { int a[4]; };\n"
"void f(S* p, int k) {\n"
" int m = 3;\n"
" if (k)\n"
" m = 2;\n"
" for (int j = m + 1; j <= 4; j++)\n"
" p->a[j-1];\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void array_index_for_decr() { void array_index_for_decr() {
check("void f()\n" check("void f()\n"
"{\n" "{\n"