From ee5c8e315733a22157e941ca20f6598bcd2bfd6e Mon Sep 17 00:00:00 2001 From: Paul Date: Mon, 3 Jan 2022 22:36:03 -0600 Subject: [PATCH 1/4] Fix 10676: FP: Array index -1 is out of bounds. --- lib/astutils.cpp | 5 ++++- lib/infer.cpp | 9 +++++++++ lib/infer.h | 3 +++ lib/valueflow.cpp | 3 +++ test/teststl.cpp | 13 +++++++++++++ 5 files changed, 32 insertions(+), 1 deletion(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 04d032ae1e4..c8793232177 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 a7e5a711293..7976151fe59 100644 --- a/lib/infer.cpp +++ b/lib/infer.cpp @@ -360,3 +360,12 @@ 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 b77e611cc1c..44e0f713b57 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/lib/valueflow.cpp b/lib/valueflow.cpp index 12c56d6694d..21b39a0956a 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -471,6 +471,9 @@ static void setTokenValue(Token* tok, ValueFlow::Value value, const Settings* se if (!value.isImpossible() && value.isIntValue()) value = truncateImplicitConversion(tok->astParent(), value, settings); + if (value.isIntValue() && tok->str() == "j" && value.isImpossible() && value.intvalue == -1) + printf("Here\n"); + if (!tok->addValue(value)) return; diff --git a/test/teststl.cpp b/test/teststl.cpp index 74c66fa5d9e..985458e25bb 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -2057,6 +2057,19 @@ class TestStl : public TestFixture { " 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()); } From 9fbe218612ab6498b861218e494913bcd611ded1 Mon Sep 17 00:00:00 2001 From: Paul Date: Mon, 3 Jan 2022 22:37:47 -0600 Subject: [PATCH 2/4] Format --- lib/infer.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/infer.cpp b/lib/infer.cpp index 7976151fe59..cc044774179 100644 --- a/lib/infer.cpp +++ b/lib/infer.cpp @@ -363,9 +363,13 @@ std::vector infer(const ValuePtr& model, std::vector getMinValue(const ValuePtr& model, const std::list& values) { - return Interval::fromValues(values, [&](const ValueFlow::Value& v) { return model->match(v); }).minvalue; + 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; + return Interval::fromValues(values, [&](const ValueFlow::Value& v) { + return model->match(v); + }).maxvalue; } From 44cca83d01ab5fe80574405b091f92d5856eb2f5 Mon Sep 17 00:00:00 2001 From: Paul Date: Mon, 3 Jan 2022 22:45:15 -0600 Subject: [PATCH 3/4] Remove debug code --- lib/valueflow.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 21b39a0956a..12c56d6694d 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -471,9 +471,6 @@ static void setTokenValue(Token* tok, ValueFlow::Value value, const Settings* se if (!value.isImpossible() && value.isIntValue()) value = truncateImplicitConversion(tok->astParent(), value, settings); - if (value.isIntValue() && tok->str() == "j" && value.isImpossible() && value.intvalue == -1) - printf("Here\n"); - if (!tok->addValue(value)) return; From 0c57281f74902b73914c5a9f951d351cc3cd5ff1 Mon Sep 17 00:00:00 2001 From: Paul Date: Mon, 3 Jan 2022 23:44:12 -0600 Subject: [PATCH 4/4] dmake --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6d687299854..c662bcf44cf 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