From 987ce5a4083b85312e1f2915fa8a6350bc2cd688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Mon, 7 Jul 2014 17:48:58 +0200 Subject: [PATCH] Fixed #5968 (False positive: 'Possible null pointer dereference' when checking null in negated conjuction) --- lib/valueflow.cpp | 29 +++++++++++++++++++++++++---- test/testvalueflow.cpp | 6 ++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 7f0ccf0aa..047a9e66f 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -895,11 +895,32 @@ static void valueFlowAfterCondition(TokenList *tokenlist, ErrorLogger *errorLogg continue; } + // start token of conditional code Token *startToken = nullptr; - if (Token::Match(tok, "==|>=|<=|!") && Token::simpleMatch(top->link(), ") {")) - startToken = top->link()->next(); - else if (Token::Match(tok, "%var%|!=") && Token::simpleMatch(top->link()->linkAt(1), "} else {")) - startToken = top->link()->linkAt(1)->tokAt(2); + + // based on the comparison, should we check the if or while? + int codeblock = 0; + if (Token::Match(tok, "==|>=|<=|!")) + codeblock = 1; + else if (Token::Match(tok, "%var%|!=")) + codeblock = 2; + + // determine startToken based on codeblock + if (codeblock > 0) { + // if astParent is "!" we need to invert codeblock + const Token *parent = tok->astParent(); + while (parent && parent->str() == "&&") + parent = parent->astParent(); + if (parent && parent->str() == "!") + codeblock = (codeblock == 1) ? 2 : 1; + + // convert codeblock to a startToken + if (codeblock == 1 && Token::simpleMatch(top->link(), ") {")) + startToken = top->link()->next(); + else if (Token::simpleMatch(top->link()->linkAt(1), "} else {")) + startToken = top->link()->linkAt(1)->tokAt(2); + } + bool ok = true; if (startToken) ok = valueFlowForward(startToken->next(), startToken->link(), var, varid, values, true, tokenlist, errorLogger, settings); diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 238f4b7e8..11e4a7a24 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -794,6 +794,12 @@ private: "}"; ASSERT_EQUALS(true, testValueOfX(code, 2U, 0)); + code = "void f(int x, int y) {\n" + " if (!(x&&y)) { return; }\n" + " a = x;\n" + "}"; + ASSERT_EQUALS(false, testValueOfX(code, 3U, 0)); + // if (var) code = "void f(int x) {\n" " if (x) { a = x; }\n" // <- x is not 0