From 119ec0582a48e54d698d46062b60d4dbaac3074e Mon Sep 17 00:00:00 2001 From: Paul Fultz II Date: Tue, 4 Jan 2022 03:21:54 -0600 Subject: [PATCH] Fix 10676: FP: Array index -1 is out of bounds. (#3670) --- Makefile | 2 +- lib/astutils.cpp | 5 ++++- lib/infer.cpp | 13 +++++++++++++ lib/infer.h | 3 +++ test/teststl.cpp | 13 +++++++++++++ 5 files changed, 34 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 6d6872998..c662bcf44 100644 --- a/Makefile +++ b/Makefile @@ -411,7 +411,7 @@ validateRules: $(libcppdir)/analyzerinfo.o: lib/analyzerinfo.cpp externals/tinyxml2/tinyxml2.h lib/analyzerinfo.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/path.h lib/platform.h lib/suppressions.h lib/utils.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/analyzerinfo.o $(libcppdir)/analyzerinfo.cpp -$(libcppdir)/astutils.o: lib/astutils.cpp lib/astutils.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/utils.h lib/valueflow.h +$(libcppdir)/astutils.o: lib/astutils.cpp lib/astutils.h lib/config.h lib/errortypes.h lib/importproject.h lib/infer.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/utils.h lib/valueflow.h lib/valueptr.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/astutils.o $(libcppdir)/astutils.cpp $(libcppdir)/bughuntingchecks.o: lib/bughuntingchecks.cpp lib/astutils.h lib/bughuntingchecks.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/exprengine.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/utils.h lib/valueflow.h diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 04d032ae1..c87932321 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -22,12 +22,14 @@ #include "config.h" #include "errortypes.h" +#include "infer.h" #include "library.h" #include "mathlib.h" #include "settings.h" #include "symboldatabase.h" #include "token.h" #include "valueflow.h" +#include "valueptr.h" #include #include @@ -687,9 +689,10 @@ bool extractForLoopValues(const Token *forToken, const Token *incExpr = forToken->next()->astOperand2()->astOperand2()->astOperand2(); if (!initExpr || !initExpr->isBinaryOp() || initExpr->str() != "=" || !Token::Match(initExpr->astOperand1(), "%var%")) return false; + std::vector minInitValue = getMinValue(makeIntegralInferModel(), initExpr->astOperand2()->values()); *varid = initExpr->astOperand1()->varId(); *knownInitValue = initExpr->astOperand2()->hasKnownIntValue(); - *initValue = (*knownInitValue) ? initExpr->astOperand2()->getKnownIntValue() : 0; + *initValue = minInitValue.empty() ? 0 : minInitValue.front(); *partialCond = Token::Match(condExpr, "%oror%|&&"); visitAstNodes(condExpr, [varid, &condExpr](const Token *tok) { if (Token::Match(tok, "%oror%|&&")) diff --git a/lib/infer.cpp b/lib/infer.cpp index a7e5a7112..cc0447741 100644 --- a/lib/infer.cpp +++ b/lib/infer.cpp @@ -360,3 +360,16 @@ std::vector infer(const ValuePtr& model, { return infer(model, op, std::move(lhsValues), {model->yield(rhs)}); } + +std::vector getMinValue(const ValuePtr& model, const std::list& values) +{ + return Interval::fromValues(values, [&](const ValueFlow::Value& v) { + return model->match(v); + }).minvalue; +} +std::vector getMaxValue(const ValuePtr& model, const std::list& values) +{ + return Interval::fromValues(values, [&](const ValueFlow::Value& v) { + return model->match(v); + }).maxvalue; +} diff --git a/lib/infer.h b/lib/infer.h index b77e611cc..44e0f713b 100644 --- a/lib/infer.h +++ b/lib/infer.h @@ -47,6 +47,9 @@ std::vector infer(const ValuePtr& model, std::list lhsValues, MathLib::bigint rhs); +std::vector getMinValue(const ValuePtr& model, const std::list& values); +std::vector getMaxValue(const ValuePtr& model, const std::list& values); + std::string toString(const Interval& i); #endif diff --git a/test/teststl.cpp b/test/teststl.cpp index 74c66fa5d..985458e25 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -2057,6 +2057,19 @@ private: " return a[4 - x];\n" "}"); ASSERT_EQUALS("", errout.str()); + + check("std::array values;\n" + "int get_value();\n" + "int compute() {\n" + " int i = get_value();\n" + " if( i < 0 || i > 5)\n" + " return -1;\n" + " int sum = 0;\n" + " for( int j = i+1; j < 7; ++j)\n" + " sum += values[j-1];\n" + " return sum;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); }