invalidTestForOverflow: Fixed some false negatives (#7184)

This commit is contained in:
Daniel Marjamäki 2015-11-30 11:12:51 +01:00
parent fb8cce647c
commit 1b0bb02f1d
3 changed files with 28 additions and 8 deletions

View File

@ -1030,12 +1030,15 @@ void CheckCondition::checkInvalidTestForOverflow()
continue; continue;
const Token *calcToken, *exprToken; const Token *calcToken, *exprToken;
if (tok->str() == "<" && tok->astOperand1()->str() == "+") { bool result;
if (Token::Match(tok, "<|>=") && tok->astOperand1()->str() == "+") {
calcToken = tok->astOperand1(); calcToken = tok->astOperand1();
exprToken = tok->astOperand2(); exprToken = tok->astOperand2();
} else if (tok->str() == ">" && tok->astOperand2()->str() == "+") { result = (tok->str() == ">=");
} else if (Token::Match(tok, ">|<=") && tok->astOperand2()->str() == "+") {
calcToken = tok->astOperand2(); calcToken = tok->astOperand2();
exprToken = tok->astOperand1(); exprToken = tok->astOperand1();
result = (tok->str() == "<=");
} else } else
continue; continue;
@ -1058,18 +1061,20 @@ void CheckCondition::checkInvalidTestForOverflow()
// Only warn when termToken is always positive // Only warn when termToken is always positive
if (termToken->valueType() && termToken->valueType()->sign == ValueType::Sign::UNSIGNED) if (termToken->valueType() && termToken->valueType()->sign == ValueType::Sign::UNSIGNED)
invalidTestForOverflow(tok); invalidTestForOverflow(tok, result);
else if (termToken->isNumber() && MathLib::isPositive(termToken->str())) else if (termToken->isNumber() && MathLib::isPositive(termToken->str()))
invalidTestForOverflow(tok); invalidTestForOverflow(tok, result);
} }
} }
} }
void CheckCondition::invalidTestForOverflow(const Token* tok) void CheckCondition::invalidTestForOverflow(const Token* tok, bool result)
{ {
std::string errmsg; std::string errmsg;
errmsg = "Invalid test for overflow '" + errmsg = "Invalid test for overflow '" +
(tok ? tok->expressionString() : std::string("x + u < x")) + (tok ? tok->expressionString() : std::string("x + u < x")) +
"'. Condition is always false unless there is overflow, and overflow is UB."; "'. Condition is always " +
std::string(result ? "true" : "false") +
" unless there is overflow, and overflow is UB.";
reportError(tok, Severity::warning, "invalidTestForOverflow", errmsg); reportError(tok, Severity::warning, "invalidTestForOverflow", errmsg);
} }

View File

@ -126,7 +126,7 @@ private:
void alwaysTrueFalseError(const Token *tok, bool knownResult); void alwaysTrueFalseError(const Token *tok, bool knownResult);
void invalidTestForOverflow(const Token* tok); void invalidTestForOverflow(const Token* tok, bool result);
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
CheckCondition c(0, settings, errorLogger); CheckCondition c(0, settings, errorLogger);
@ -142,7 +142,7 @@ private:
c.moduloAlwaysTrueFalseError(0, "1"); c.moduloAlwaysTrueFalseError(0, "1");
c.clarifyConditionError(0, true, false); c.clarifyConditionError(0, true, false);
c.alwaysTrueFalseError(0, true); c.alwaysTrueFalseError(0, true);
c.invalidTestForOverflow(0); c.invalidTestForOverflow(0, false);
} }
static std::string myName() { static std::string myName() {

View File

@ -1613,6 +1613,21 @@ private:
"}"); "}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Invalid test for overflow '(p+x)<p'. Condition is always false unless there is overflow, and overflow is UB.\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (warning) Invalid test for overflow '(p+x)<p'. Condition is always false unless there is overflow, and overflow is UB.\n", errout.str());
check("void f(char *p, unsigned int x) {\n"
" assert((p + x) >= p);\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Invalid test for overflow '(p+x)>=p'. Condition is always true unless there is overflow, and overflow is UB.\n", errout.str());
check("void f(char *p, unsigned int x) {\n"
" assert(p > (p + x));\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Invalid test for overflow 'p>(p+x)'. Condition is always false unless there is overflow, and overflow is UB.\n", errout.str());
check("void f(char *p, unsigned int x) {\n"
" assert(p <= (p + x));\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Invalid test for overflow 'p<=(p+x)'. Condition is always true unless there is overflow, and overflow is UB.\n", errout.str());
check("void f(signed int x) {\n" check("void f(signed int x) {\n"
" assert(x + 100 < x);\n" " assert(x + 100 < x);\n"
"}"); "}");