From 8d75d1b920466a2b3f52defb8e69df9472ef51f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Mon, 15 May 2017 20:05:11 +0200 Subject: [PATCH] Partial fix for #8028 (ValueFlow: Origin/callstack of value) --- Makefile | 2 +- lib/check.h | 17 +++++++ lib/checknullpointer.cpp | 76 ++++++++++++++-------------- lib/checknullpointer.h | 11 +++-- lib/checkother.cpp | 39 ++++++--------- lib/checkother.h | 6 +-- lib/settings.cpp | 10 ++++ lib/settings.h | 10 ++++ lib/valueflow.cpp | 6 +++ lib/valueflow.h | 7 ++- test/testnullpointer.cpp | 104 +++++++++++++++++++-------------------- 11 files changed, 163 insertions(+), 125 deletions(-) diff --git a/Makefile b/Makefile index 7a633ad33..e0fea66a5 100644 --- a/Makefile +++ b/Makefile @@ -411,7 +411,7 @@ $(SRCDIR)/platform.o: lib/platform.cpp lib/cxx11emu.h lib/platform.h lib/config. $(SRCDIR)/preprocessor.o: lib/preprocessor.cpp lib/cxx11emu.h lib/preprocessor.h lib/config.h lib/path.h lib/errorlogger.h lib/suppressions.h lib/settings.h lib/library.h lib/mathlib.h lib/standards.h lib/platform.h lib/importproject.h lib/timer.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(SRCDIR)/preprocessor.o $(SRCDIR)/preprocessor.cpp -$(SRCDIR)/settings.o: lib/settings.cpp lib/cxx11emu.h lib/settings.h lib/config.h lib/library.h lib/mathlib.h lib/standards.h lib/errorlogger.h lib/suppressions.h lib/platform.h lib/importproject.h lib/timer.h lib/preprocessor.h lib/utils.h +$(SRCDIR)/settings.o: lib/settings.cpp lib/cxx11emu.h lib/settings.h lib/config.h lib/library.h lib/mathlib.h lib/standards.h lib/errorlogger.h lib/suppressions.h lib/platform.h lib/importproject.h lib/timer.h lib/preprocessor.h lib/utils.h lib/valueflow.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(SRCDIR)/settings.o $(SRCDIR)/settings.cpp $(SRCDIR)/suppressions.o: lib/suppressions.cpp lib/cxx11emu.h lib/suppressions.h lib/config.h lib/path.h diff --git a/lib/check.h b/lib/check.h index 59d4755ce..605316d2a 100644 --- a/lib/check.h +++ b/lib/check.h @@ -158,6 +158,23 @@ protected: reportError(errmsg); } + std::list getErrorPath(const Token *errtok, const ValueFlow::Value *value) const { + std::list errorPath; + if (!value) { + errorPath.push_back(errtok); + } else if (_settings->verbose) { + errorPath = value->callstack; + errorPath.push_back(errtok); + } else { + if (value->condition) + errorPath.push_back(value->condition); + //else if (!value->isKnown() || value->defaultArg) + // errorPath = value->callstack; + errorPath.push_back(errtok); + } + return errorPath; + } + private: const std::string _name; diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index 41fdb2134..ab1611ed6 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -275,6 +275,7 @@ void CheckNullPointer::nullPointerLinkedList() continue; // Check usage of dereferenced variable in the loop.. + // TODO: Move this to ValueFlow for (std::list::const_iterator j = i->nestedList.begin(); j != i->nestedList.end(); ++j) { const Scope* const scope = *j; if (scope->type != Scope::eWhile) @@ -287,7 +288,8 @@ void CheckNullPointer::nullPointerLinkedList() // for statement. for (const Token *tok4 = scope->classStart; tok4; tok4 = tok4->next()) { if (tok4 == i->classEnd) { - nullPointerError(tok1, var->name(), scope->classDef, false); + const ValueFlow::Value v(scope->classDef, 0LL); + nullPointerError(tok1, var->name(), &v, false); break; } @@ -306,7 +308,6 @@ void CheckNullPointer::nullPointerLinkedList() void CheckNullPointer::nullPointerByDeRefAndChec() { - const bool printWarnings = _settings->isEnabled(Settings::WARNING); const bool printInconclusive = (_settings->inconclusive); for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { @@ -340,10 +341,7 @@ void CheckNullPointer::nullPointerByDeRefAndChec() std::list varlist; parseFunctionCall(*ftok->previous(), varlist, &_settings->library); if (std::find(varlist.begin(), varlist.end(), tok) != varlist.end()) { - if (value->condition == nullptr) - nullPointerError(tok, tok->str(), false, value->defaultArg, !value->isKnown()); - else if (printWarnings) - nullPointerError(tok, tok->str(), value->condition, value->inconclusive); + nullPointerError(tok, tok->str(), value, value->inconclusive); } continue; } @@ -351,19 +349,12 @@ void CheckNullPointer::nullPointerByDeRefAndChec() // Pointer dereference. bool unknown = false; if (!isPointerDeRef(tok,unknown)) { - if (printInconclusive && unknown) { - if (value->condition == nullptr) - nullPointerError(tok, tok->str(), true, value->defaultArg, !value->isKnown()); - else - nullPointerError(tok, tok->str(), value->condition, true); - } + if (unknown) + nullPointerError(tok, tok->str(), value, true); continue; } - if (value->condition == nullptr) - nullPointerError(tok, tok->str(), value->inconclusive, value->defaultArg, !value->isKnown()); - else if (printWarnings) - nullPointerError(tok, tok->str(), value->condition, value->inconclusive); + nullPointerError(tok, tok->str(), value, value->inconclusive); } } @@ -462,32 +453,39 @@ void CheckNullPointer::nullConstantDereference() } } -void CheckNullPointer::nullPointerError(const Token *tok) +void CheckNullPointer::nullPointerError(const Token *tok, const std::string &varname, const ValueFlow::Value *value, bool inconclusive) { - reportError(tok, Severity::error, "nullPointer", "Null pointer dereference", CWE476, false); -} + const std::string errmsgcond(ValueFlow::eitherTheConditionIsRedundant(value ? value->condition : nullptr) + " or there is possible null pointer dereference: " + varname + "."); + const std::string errmsgdefarg("Possible null pointer dereference if the default parameter value is used: " + varname); -void CheckNullPointer::nullPointerError(const Token *tok, const std::string &varname, bool inconclusive, bool defaultArg, bool possible) -{ - if (defaultArg) { - if (_settings->isEnabled(Settings::WARNING)) - reportError(tok, Severity::warning, "nullPointerDefaultArg", "Possible null pointer dereference if the default parameter value is used: " + varname, CWE476, inconclusive); - } else if (possible) { - if (_settings->isEnabled(Settings::WARNING)) - reportError(tok, Severity::warning, "nullPointer", "Possible null pointer dereference: " + varname, CWE476, inconclusive); - } else - reportError(tok, Severity::error, "nullPointer", "Null pointer dereference: " + varname, CWE476, inconclusive); -} - -void CheckNullPointer::nullPointerError(const Token *tok, const std::string &varname, const Token* nullCheck, bool inconclusive) -{ - if (! _settings->isEnabled(Settings::WARNING)) + if (!tok) { + reportError(tok, Severity::error, "nullPointer", "Null pointer dereference", CWE476, false); + reportError(tok, Severity::warning, "nullPointerDefaultArg", errmsgdefarg, CWE476, false); + reportError(tok, Severity::warning, "nullPointerRedundantCheck", errmsgcond, CWE476, false); return; - std::list callstack; - callstack.push_back(tok); - callstack.push_back(nullCheck); - const std::string errmsg(ValueFlow::eitherTheConditionIsRedundant(nullCheck) + " or there is possible null pointer dereference: " + varname + "."); - reportError(callstack, Severity::warning, "nullPointerRedundantCheck", errmsg, CWE476, inconclusive); + } + + if (!_settings->isEnabled(value, inconclusive)) + return; + + const std::list errorPath = getErrorPath(tok,value); + + if (value->condition) { + reportError(errorPath, Severity::warning, "nullPointerRedundantCheck", errmsgcond, CWE476, inconclusive || value->inconclusive); + } else if (value->defaultArg) { + reportError(errorPath, Severity::warning, "nullPointerDefaultArg", errmsgdefarg, CWE476, inconclusive || value->inconclusive); + } else { + std::string errmsg; + errmsg = std::string(value->isKnown() ? "Null" : "Possible null") + " pointer dereference"; + if (!varname.empty()) + errmsg += ": " + varname; + + reportError(errorPath, + value->isKnown() ? Severity::error : Severity::warning, + "nullPointer", + errmsg, + CWE476, inconclusive || value->inconclusive); + } } void CheckNullPointer::arithmetic() diff --git a/lib/checknullpointer.h b/lib/checknullpointer.h index ef70dde3e..2189330cd 100644 --- a/lib/checknullpointer.h +++ b/lib/checknullpointer.h @@ -83,16 +83,17 @@ public: /** @brief dereferencing null constant (after Tokenizer::simplifyKnownVariables) */ void nullConstantDereference(); - void nullPointerError(const Token *tok); // variable name unknown / doesn't exist - void nullPointerError(const Token *tok, const std::string &varname, bool inconclusive, bool defaultArg, bool possible); - void nullPointerError(const Token *tok, const std::string &varname, const Token* nullCheck, bool inconclusive); + void nullPointerError(const Token *tok) { + ValueFlow::Value v(0); + v.setKnown(); + nullPointerError(tok, "", &v, false); + } + void nullPointerError(const Token *tok, const std::string &varname, const ValueFlow::Value* value, bool inconclusive); private: /** Get error messages. Used by --errorlist */ void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { CheckNullPointer c(nullptr, settings, errorLogger); - c.nullPointerError(nullptr); - c.nullPointerError(nullptr, "pointer", false, true, true); c.nullPointerError(nullptr, "pointer", nullptr, false); c.arithmeticError(nullptr, nullptr); } diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 8061bebdf..46e65070c 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1625,9 +1625,6 @@ void CheckOther::constStatementError(const Token *tok, const std::string &type) //--------------------------------------------------------------------------- void CheckOther::checkZeroDivision() { - const bool printWarnings = _settings->isEnabled(Settings::WARNING); - const bool printInconclusive = _settings->inconclusive; - for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { if (!tok->astOperand2() || !tok->astOperand1()) continue; @@ -1646,31 +1643,27 @@ void CheckOther::checkZeroDivision() // Value flow.. const ValueFlow::Value *value = tok->astOperand2()->getValue(0LL); - if (!value) - continue; - if (!printInconclusive && value->inconclusive) - continue; - if (value->condition == nullptr) - zerodivError(tok, value->inconclusive); - else if (printWarnings) - zerodivcondError(value->condition,tok,value->inconclusive); + if (value && _settings->isEnabled(value, false)) + zerodivError(tok, value); } } -void CheckOther::zerodivError(const Token *tok, bool inconclusive) +void CheckOther::zerodivError(const Token *tok, const ValueFlow::Value *value) { - reportError(tok, Severity::error, "zerodiv", "Division by zero.", CWE369, inconclusive); -} - -void CheckOther::zerodivcondError(const Token *tokcond, const Token *tokdiv, bool inconclusive) -{ - std::list callstack; - if (tokcond && tokdiv) { - callstack.push_back(tokcond); - callstack.push_back(tokdiv); + if (!tok && !value) { + reportError(tok, Severity::error, "zerodiv", "Division by zero.", CWE369, false); + reportError(tok, Severity::error, "zerodivcond", ValueFlow::eitherTheConditionIsRedundant(nullptr) + " or there is division by zero.", CWE369, false); + return; + } + + const std::list errorPath = getErrorPath(tok, value); + + if (!value->condition) + reportError(errorPath, Severity::error, "zerodiv", "Division by zero.", CWE369, value->inconclusive); + else { + const std::string linenr(MathLib::toString(tok->linenr())); + reportError(errorPath, Severity::warning, "zerodivcond", ValueFlow::eitherTheConditionIsRedundant(value->condition) + " or there is division by zero at line " + linenr + ".", CWE369, value->inconclusive); } - const std::string linenr(MathLib::toString(tokdiv ? tokdiv->linenr() : 0)); - reportError(callstack, Severity::warning, "zerodivcond", ValueFlow::eitherTheConditionIsRedundant(tokcond) + " or there is division by zero at line " + linenr + ".", CWE369, inconclusive); } //--------------------------------------------------------------------------- diff --git a/lib/checkother.h b/lib/checkother.h index f89cf5d1c..79a715975 100644 --- a/lib/checkother.h +++ b/lib/checkother.h @@ -218,8 +218,7 @@ private: void unknownSignCharArrayIndexError(const Token *tok); void charBitOpError(const Token *tok); void variableScopeError(const Token *tok, const std::string &varname); - void zerodivError(const Token *tok, bool inconclusive); - void zerodivcondError(const Token *tokcond, const Token *tokdiv, bool inconclusive); + void zerodivError(const Token *tok, const ValueFlow::Value *value); void nanInArithmeticExpressionError(const Token *tok); void redundantAssignmentError(const Token *tok1, const Token* tok2, const std::string& var, bool inconclusive); void redundantAssignmentInSwitchError(const Token *tok1, const Token *tok2, const std::string &var); @@ -258,8 +257,7 @@ private: CheckOther c(nullptr, settings, errorLogger); // error - c.zerodivError(nullptr, false); - c.zerodivcondError(nullptr, 0,false); + c.zerodivError(nullptr, nullptr); c.misusedScopeObjectError(nullptr, "varname"); c.invalidPointerCastError(nullptr, "float", "double", false); c.negativeBitwiseShiftError(nullptr, 1); diff --git a/lib/settings.cpp b/lib/settings.cpp index 600decb6a..4212c27de 100644 --- a/lib/settings.cpp +++ b/lib/settings.cpp @@ -19,6 +19,7 @@ #include "settings.h" #include "preprocessor.h" // Preprocessor #include "utils.h" +#include "valueflow.h" #include #include @@ -129,3 +130,12 @@ bool Settings::isEnabled(Severity::SeverityType severity) const return false; } } + +bool Settings::isEnabled(const ValueFlow::Value *value, bool inconclusiveCheck) const +{ + if (!isEnabled(Settings::WARNING) && (!value->isKnown() || value->condition || value->defaultArg)) + return false; + if (!inconclusive && (inconclusiveCheck || value->inconclusive)) + return false; + return true; +} diff --git a/lib/settings.h b/lib/settings.h index 13dba8703..d5cc2b143 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -34,6 +34,10 @@ #include "errorlogger.h" #include "timer.h" +namespace ValueFlow { + class Value; +} + /// @addtogroup Core /// @{ @@ -178,6 +182,12 @@ public: */ bool isEnabled(Severity::SeverityType severity) const; + /** + * @brief Returns true if given value can be shown + * @return true if the value can be shown + */ + bool isEnabled(const ValueFlow::Value *value, bool inconclusiveCheck=false) const; + /** * @brief Enable extra checks by id. See isEnabled() * @param str single id or list of id values to be enabled diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 575ebba70..1470fffc5 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1970,6 +1970,8 @@ static void valueFlowAfterAssign(TokenList *tokenlist, SymbolDatabase* symboldat continue; std::list values = tok->astOperand2()->values(); + for (std::list::iterator it = values.begin(); it != values.end(); ++it) + it->callstack.push_back(tok->astOperand2()); const bool constValue = tok->astOperand2()->isNumber(); if (tokenlist->isCPP() && Token::Match(var->typeStartToken(), "bool|_Bool")) { @@ -2768,6 +2770,10 @@ static void valueFlowSubFunction(TokenList *tokenlist, ErrorLogger *errorLogger, } } + // callstack.. + for (std::list::iterator it = argvalues.begin(); it != argvalues.end(); ++it) + it->callstack.push_back(argtok); + // passed values are not "known".. for (std::list::iterator it = argvalues.begin(); it != argvalues.end(); ++it) { it->changeKnownToPossible(); diff --git a/lib/valueflow.h b/lib/valueflow.h index 90163803f..01a9fddff 100644 --- a/lib/valueflow.h +++ b/lib/valueflow.h @@ -21,6 +21,7 @@ #define valueflowH //--------------------------------------------------------------------------- +#include #include #include "config.h" @@ -34,7 +35,9 @@ namespace ValueFlow { class CPPCHECKLIB Value { public: explicit Value(long long val = 0) : valueType(INT), intvalue(val), tokvalue(nullptr), floatValue(0.0), moveKind(NonMovedVariable), varvalue(val), condition(0), varId(0U), conditional(false), inconclusive(false), defaultArg(false), valueKind(ValueKind::Possible) {} - Value(const Token *c, long long val) : valueType(INT), intvalue(val), tokvalue(nullptr), floatValue(0.0), moveKind(NonMovedVariable), varvalue(val), condition(c), varId(0U), conditional(false), inconclusive(false), defaultArg(false), valueKind(ValueKind::Possible) {} + Value(const Token *c, long long val) : valueType(INT), intvalue(val), tokvalue(nullptr), floatValue(0.0), moveKind(NonMovedVariable), varvalue(val), condition(c), varId(0U), conditional(false), inconclusive(false), defaultArg(false), valueKind(ValueKind::Possible) { + callstack.push_back(c); + } bool operator==(const Value &rhs) const { if (valueType != rhs.valueType) @@ -105,6 +108,8 @@ namespace ValueFlow { /** Condition that this value depends on (TODO: replace with a 'callstack') */ const Token *condition; + std::list callstack; + /** For calculated values - varId that calculated value depends on */ unsigned int varId; diff --git a/test/testnullpointer.cpp b/test/testnullpointer.cpp index 1c1c7e0dd..872f749d3 100644 --- a/test/testnullpointer.cpp +++ b/test/testnullpointer.cpp @@ -111,7 +111,7 @@ private: if (!tokenizer.tokenize(istr, filename)) return; - // Check for redundant code.. + // Check for null pointer dereferences.. CheckNullPointer checkNullPointer; checkNullPointer.runChecks(&tokenizer, &settings, this); @@ -127,7 +127,7 @@ private: " while (tok);\n" " tok = tok->next();\n" "}", true); - ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (warning, inconclusive) Either the condition 'tok' is redundant or there is possible null pointer dereference: tok.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning, inconclusive) Either the condition 'tok' is redundant or there is possible null pointer dereference: tok.\n", errout.str()); // #2681 { @@ -144,7 +144,7 @@ private: ASSERT_EQUALS("", errout.str()); check(code, true); // inconclusive=true => error - ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:3]: (warning, inconclusive) Either the condition 'tok' is redundant or there is possible null pointer dereference: tok.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:6]: (warning, inconclusive) Either the condition 'tok' is redundant or there is possible null pointer dereference: tok.\n", errout.str()); } check("void foo()\n" @@ -155,7 +155,7 @@ private: " tok = tok->next();\n" " }\n" "}"); - ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:5]: (warning) Either the condition 'while' is redundant or there is possible null pointer dereference: tok.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:3]: (warning) Either the condition 'while' is redundant or there is possible null pointer dereference: tok.\n", errout.str()); check("void foo(Token &tok)\n" "{\n" @@ -281,7 +281,7 @@ private: " if (!abc)\n" " ;\n" "}"); - ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc.\n", errout.str()); check("void foo(struct ABC *abc) {\n" " bar(abc->a);\n" @@ -290,9 +290,9 @@ private: " if (!abc)\n" " ;\n" "}"); - ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:5]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc.\n" - "[test.cpp:3] -> [test.cpp:5]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc.\n" - "[test.cpp:4] -> [test.cpp:5]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:2]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc.\n" + "[test.cpp:5] -> [test.cpp:3]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc.\n" + "[test.cpp:5] -> [test.cpp:4]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc.\n", errout.str()); check("void foo(ABC *abc) {\n" " if (abc->a == 3) {\n" @@ -300,7 +300,7 @@ private: " }\n" " if (abc) {}\n" "}"); - ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:5]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:2]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n", errout.str()); check("void f(ABC *abc) {\n" " if (abc->x == 0) {\n" @@ -308,7 +308,7 @@ private: " }\n" " if (!abc);\n" "}"); - ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:5]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:2]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc.\n", errout.str()); // TODO: False negative if member of member is dereferenced check("void foo(ABC *abc) {\n" @@ -316,14 +316,14 @@ private: " if (abc->next)\n" " ;\n" "}"); - TODO_ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Possible null pointer dereference: abc - otherwise it is redundant to check it against null.\n", "", errout.str()); + TODO_ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Possible null pointer dereference: abc - otherwise it is redundant to check it against null.\n", "", errout.str()); check("void foo(ABC *abc) {\n" " abc->a = 0;\n" " if (abc && abc->b == 0)\n" " ;\n" "}"); - ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition 'if(abc&&abc->b==0)' is redundant or there is possible null pointer dereference: abc.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'if(abc&&abc->b==0)' is redundant or there is possible null pointer dereference: abc.\n", errout.str()); // ok dereferencing in a condition check("void foo(struct ABC *abc)\n" @@ -446,7 +446,7 @@ private: " do_stuff();\n" " if (abc) { }\n" "}"); - ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:5]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n",errout.str()); + ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:3]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n",errout.str()); // #2641 - local pointer, function call check("void f(ABC *abc) {\n" @@ -454,7 +454,7 @@ private: " do_stuff();\n" " if (abc) { }\n" "}"); - ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n",errout.str()); + ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n",errout.str()); // #2691 - switch/break check("void f(ABC *abc) {\n" @@ -503,7 +503,7 @@ private: check(code); ASSERT_EQUALS("", errout.str()); check(code, true); - ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning, inconclusive) Either the condition 'if(fred)' is redundant or there is possible null pointer dereference: fred.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning, inconclusive) Either the condition 'if(fred)' is redundant or there is possible null pointer dereference: fred.\n", errout.str()); } // #3425 - false positives when there are macros @@ -523,21 +523,21 @@ private: " if (!p)\n" " ;\n" "}"); - ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); check("void foo(int *p)\n" "{\n" " *p = 0;\n" " if (p) { }\n" "}"); - ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (warning) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str()); check("void foo(int *p)\n" "{\n" " *p = 0;\n" " if (p || q) { }\n" "}"); - ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Either the condition 'if(p||q)' is redundant or there is possible null pointer dereference: p.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (warning) Either the condition 'if(p||q)' is redundant or there is possible null pointer dereference: p.\n", errout.str()); check("void foo(int *p)\n" "{\n" @@ -545,7 +545,7 @@ private: " if (!p)\n" " ;\n" "}"); - ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); check("void foo(char *p)\n" "{\n" @@ -553,14 +553,14 @@ private: " if (!p)\n" " ;\n" "}"); - ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); check("void foo(char *p)\n" "{\n" " if (*p == 0) { }\n" " if (!p) { }\n" "}"); - ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); // no error check("void foo()\n" @@ -613,7 +613,7 @@ private: " if (!p)\n" " ;\n" "}"); - ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); // while check("void f(int *p) {\n" @@ -626,7 +626,7 @@ private: " *p = 0;\n" " while (p) { }\n" "}"); - ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition 'while(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'while(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str()); // Ticket #3125 check("void foo(ABC *p)\n" @@ -703,7 +703,7 @@ private: " assert(p && (*p<=6));\n" " if (p) { *p = 0; }\n" "}"); - ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (warning) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str()); check("void foo(x *p)\n" "{\n" @@ -768,7 +768,7 @@ private: " a = b ? c : d;\n" " if (item) { }\n" "}"); - ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning) Either the condition 'if(item)' is redundant or there is possible null pointer dereference: item.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (warning) Either the condition 'if(item)' is redundant or there is possible null pointer dereference: item.\n", errout.str()); check("BOOL GotoFlyAnchor()\n" // #2243 "{\n" @@ -1315,7 +1315,7 @@ private: " }\n" " }\n" "}\n", true); - ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning, inconclusive) Either the condition 'if(values)' is redundant or there is possible null pointer dereference: values.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (warning, inconclusive) Either the condition 'if(values)' is redundant or there is possible null pointer dereference: values.\n", errout.str()); } void nullpointer_addressOf() { // address of @@ -1373,27 +1373,27 @@ private: " }\n" " *p = 0;\n" "}"); - ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); check("void foo(char *p) {\n" " if (p && *p == 0) {\n" " }\n" " printf(\"%c\", *p);\n" "}"); - ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); check("void foo(char *p) {\n" " if (p && *p == 0) {\n" " } else { *p = 0; }\n" "}"); - ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); check("void foo(char *p) {\n" " if (p) {\n" " }\n" " strcpy(p, \"abc\");\n" "}"); - ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); check("void foo(char *p) {\n" " if (p) {\n" @@ -1401,7 +1401,7 @@ private: " bar();\n" " strcpy(p, \"abc\");\n" "}"); - ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:2]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:5]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); check("void foo(abc *p) {\n" " if (!p) {\n" @@ -1470,8 +1470,8 @@ private: " return 5+*p;\n" " }\n" "}"); - ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n" - "[test.cpp:4] -> [test.cpp:2]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n" + "[test.cpp:2] -> [test.cpp:4]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); // operator! check("void f() {\n" @@ -1507,7 +1507,7 @@ private: " }\n" " *p = 0;\n" "}"); - ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:2]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:5]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); // #2467 - unknown macro may terminate the application check("void f(Fred *fred) {\n" @@ -1607,7 +1607,7 @@ private: " if (fred) { }\n" " return fred->a;\n" "}"); - ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'fred' is redundant or there is possible null pointer dereference: fred.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition 'fred' is redundant or there is possible null pointer dereference: fred.\n", errout.str()); // #2789 - assign and check pointer check("void f() {\n" @@ -1615,7 +1615,7 @@ private: " if (!p) { }\n" " *p = 0;\n" "}"); - ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); // check, assign and use check("void f() {\n" @@ -1689,7 +1689,7 @@ private: ASSERT_EQUALS("", errout.str()); check(code, true); // inconclusive - ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning, inconclusive) Either the condition 'fred==NULL' is redundant or there is possible null pointer dereference: fred.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning, inconclusive) Either the condition 'fred==NULL' is redundant or there is possible null pointer dereference: fred.\n", errout.str()); } check("void f(char *s) {\n" // #3358 @@ -1722,7 +1722,7 @@ private: " if (!p) {}\n" " return q ? p->x : 0;\n" "}"); - ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); check("int f(ABC *p) {\n" // FP : return && " if (!p) {}\n" @@ -1734,7 +1734,7 @@ private: " if (x || !p) {}\n" " *p = 0;\n" "}"); - ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str()); // sizeof check("void f() {\n" @@ -2131,7 +2131,7 @@ private: "}", false); ASSERT_EQUALS("[test.cpp:3]: (error) Null pointer dereference: p\n" "[test.cpp:4]: (error) Null pointer dereference: p\n" - "[test.cpp:6] -> [test.cpp:5]: (warning) Either the condition 'q==0' is redundant or there is possible null pointer dereference: q.\n", errout.str()); + "[test.cpp:5] -> [test.cpp:6]: (warning) Either the condition 'q==0' is redundant or there is possible null pointer dereference: q.\n", errout.str()); check("void f(const char* p) {\n" " if(p == 0) {\n" @@ -2141,12 +2141,12 @@ private: " std::cout << abc << p;\n" " }\n" "}", false); - TODO_ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n" - "[test.cpp:4] -> [test.cpp:2]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n" - "[test.cpp:5] -> [test.cpp:2]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n" - "[test.cpp:6] -> [test.cpp:2]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n", - "[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n" - "[test.cpp:4] -> [test.cpp:2]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n", + TODO_ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n" + "[test.cpp:2] -> [test.cpp:4]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n" + "[test.cpp:2] -> [test.cpp:5]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n" + "[test.cpp:2] -> [test.cpp:6]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n", + "[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n" + "[test.cpp:2] -> [test.cpp:4]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n", errout.str()); check("void f() {\n" @@ -2210,7 +2210,7 @@ private: " foo(p);\n" " if (p) { }\n" "}"); - ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:6]: (warning) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:4]: (warning) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str()); // function seen (taking reference parameter) check("void foo(int *&p) { }\n" @@ -2230,7 +2230,7 @@ private: " foo(p);\n" " if (p) { }\n" "}"); - ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:6]: (warning) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:4]: (warning) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str()); // inconclusive check("void f(int *p) {\n" @@ -2238,7 +2238,7 @@ private: " foo(p);\n" " if (p) { }\n" "}", true); - ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning, inconclusive) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (warning, inconclusive) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str()); } // dereference struct pointer and then check if it's null @@ -2259,7 +2259,7 @@ private: " foo(abc);\n" " if (abc) { }\n" "}"); - ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:6]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:4]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n", errout.str()); // function implementation not seen check("void foo(struct ABC *abc);\n" @@ -2269,7 +2269,7 @@ private: " foo(abc);\n" " if (abc) { }\n" "}"); - ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:6]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:4]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n", errout.str()); // inconclusive check("void f(struct ABC *abc) {\n" @@ -2277,7 +2277,7 @@ private: " foo(abc);\n" " if (abc) { }\n" "}", true); - ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning, inconclusive) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (warning, inconclusive) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n", errout.str()); } }