From be900873cc00a773c8ea9131e6f69b1be948794e Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 11 Sep 2020 16:03:57 -0500 Subject: [PATCH] FIx issue 9895: ValueFlow: Wrong known value below function call with reference parameter --- lib/programmemory.cpp | 43 +++++++++++++++++++++++++++--------------- lib/programmemory.h | 1 + test/testvalueflow.cpp | 29 ++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/lib/programmemory.cpp b/lib/programmemory.cpp index 4676b0af3..6b0e2d8ed 100644 --- a/lib/programmemory.cpp +++ b/lib/programmemory.cpp @@ -5,19 +5,30 @@ #include "symboldatabase.h" #include #include +#include void ProgramMemory::setValue(nonneg int varid, const ValueFlow::Value &value) { values[varid] = value; } +const ValueFlow::Value* ProgramMemory::getValue(nonneg int varid) const +{ + const ProgramMemory::Map::const_iterator it = values.find(varid); + const bool found = it != values.end() && !it->second.isImpossible(); + if (found) + return &it->second; + else + return nullptr; +} bool ProgramMemory::getIntValue(nonneg int varid, MathLib::bigint* result) const { - const ProgramMemory::Map::const_iterator it = values.find(varid); - const bool found = it != values.end() && it->second.isIntValue(); - if (found) - *result = it->second.intvalue; - return found; + const ValueFlow::Value* value = getValue(varid); + if (value && value->isIntValue()) { + *result = value->intvalue; + return true; + } + return false; } void ProgramMemory::setIntValue(nonneg int varid, MathLib::bigint value) @@ -27,20 +38,22 @@ void ProgramMemory::setIntValue(nonneg int varid, MathLib::bigint value) bool ProgramMemory::getTokValue(nonneg int varid, const Token** result) const { - const ProgramMemory::Map::const_iterator it = values.find(varid); - const bool found = it != values.end() && it->second.isTokValue(); - if (found) - *result = it->second.tokvalue; - return found; + const ValueFlow::Value* value = getValue(varid); + if (value && value->isTokValue()) { + *result = value->tokvalue; + return true; + } + return false; } bool ProgramMemory::getContainerSizeValue(nonneg int varid, MathLib::bigint* result) const { - const ProgramMemory::Map::const_iterator it = values.find(varid); - const bool found = it != values.end() && it->second.isContainerSizeValue(); - if (found) - *result = it->second.intvalue; - return found; + const ValueFlow::Value* value = getValue(varid); + if (value && value->isContainerSizeValue()) { + *result = value->intvalue; + return true; + } + return false; } void ProgramMemory::setUnknown(nonneg int varid) diff --git a/lib/programmemory.h b/lib/programmemory.h index 339026955..fb00b539c 100644 --- a/lib/programmemory.h +++ b/lib/programmemory.h @@ -15,6 +15,7 @@ struct ProgramMemory { Map values; void setValue(nonneg int varid, const ValueFlow::Value &value); + const ValueFlow::Value* getValue(nonneg int varid) const; bool getIntValue(nonneg int varid, MathLib::bigint* result) const; void setIntValue(nonneg int varid, MathLib::bigint value); diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 215d6f8bc..ba990f833 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -164,6 +164,24 @@ private: return false; } + bool testValueOfXImpossible(const char code[], unsigned int linenr, int value) { + // Tokenize.. + Tokenizer tokenizer(&settings, this); + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + + for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) { + if (tok->str() == "x" && tok->linenr() == linenr) { + for (const ValueFlow::Value& val:tok->values()) { + if (val.isImpossible() && val.intvalue == value) + return true; + } + } + } + + return false; + } + bool testValueOfX(const char code[], unsigned int linenr, int value) { // Tokenize.. Tokenizer tokenizer(&settings, this); @@ -2449,6 +2467,17 @@ private: " return x;\n" "}\n"; ASSERT_EQUALS(true, testValueOfX(code, 9U, 0)); + + code = "void g(long& a);\n" + "void f(long a) {\n" + " if (a == 0)\n" + " return;\n" + " if (a > 1)\n" + " g(a);\n" + " int x = a;\n" + " return x;\n" + "}\n"; + ASSERT_EQUALS(false, testValueOfXImpossible(code, 8U, 0)); } void valueFlowAfterConditionExpr() {