invalidTestForOverflow: Fixed some false negatives (#7184)
This commit is contained in:
parent
fb8cce647c
commit
1b0bb02f1d
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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"
|
||||||
"}");
|
"}");
|
||||||
|
|
Loading…
Reference in New Issue