From fadc27092e502b02d43ed9a07d3ace1ac59d38c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Thu, 1 May 2014 15:15:26 +0200 Subject: [PATCH] Fixed #5752 (FP (error) Possible null pointer dereference) --- lib/valueflow.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++ test/testvalueflow.cpp | 8 ++++++++ 2 files changed, 52 insertions(+) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 11ccc542e..f563ceb6a 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -28,6 +28,11 @@ #include +static void execute(const Token *expr, + std::map * const programMemory, + MathLib::bigint *result, + bool *error); + //static void printvalues(const Token *tok) //{ // if (tok->values.empty()) @@ -100,6 +105,29 @@ static bool bailoutFunctionPar(const Token *tok, const ValueFlow::Value &value, return arg && !arg->isConst() && arg->isReference(); } +/** + * Is condition always false when variable has given value? + * \param condition top ast token in condition + * \param varid variable id for variable + * \param value value of variable + */ +static bool conditionIsFalse(const Token *condition, unsigned int varid, const ValueFlow::Value &value) +{ + if (!condition) + return false; + if (condition->str() == "&&") { + bool result1 = conditionIsFalse(condition->astOperand1(), varid, value); + bool result2 = result1 ? true : conditionIsFalse(condition->astOperand2(), varid, value); + return result2; + } + std::map programMemory; + programMemory[varid] = value.intvalue; + MathLib::bigint result = 0; + bool error = false; + execute(condition, &programMemory, &result, &error); + return !error && result == 0; +} + /** * Should value be skipped because it's hidden inside && || or ?: expression. * Example: ((x!=NULL) && (*x == 123)) @@ -552,6 +580,22 @@ static void valueFlowAfterAssign(TokenList *tokenlist, ErrorLogger *errorLogger, // conditional block of code that assigns variable.. else if (Token::Match(tok2, "%var% (") && Token::simpleMatch(tok2->linkAt(1), ") {")) { + // Should scope be skipped because variable value is checked? + bool skip = false; + for (std::list::iterator it = values.begin(); it != values.end(); ++it) { + if (conditionIsFalse(tok2->next()->astOperand2(), varid, *it)) { + skip = true; + break; + } + } + if (skip) { + // goto '{' + tok2 = tok2->linkAt(1)->next(); + // goto '}' + tok2 = tok2->link(); + continue; + } + Token * const start = tok2->linkAt(1)->next(); Token * const end = start->link(); bool varusage = (indentlevel >= 0 && constValue && number_of_if == 0U) ? diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 0637128ba..ed949619d 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -655,6 +655,14 @@ private: "}"; ASSERT_EQUALS(false, testValueOfX(code, 7U, 0)); + code = "void f() {\n" // #5752 - FP + " int *x = 0;\n" + " if (x && *x == 123) {\n" + " getx(*x);\n" + " }\n" + "}"; + ASSERT_EQUALS(false, testValueOfX(code, 4U, 0)); + // multivariables code = "void f(int a) {\n" " int x = a;\n"