Fixed #4173: New check: arithmetical usage of inf/nan result

This commit is contained in:
Zachary Blair 2013-06-09 23:13:08 -07:00
parent f359bfca9c
commit 28c0045f36
3 changed files with 75 additions and 1 deletions

View File

@ -2112,6 +2112,30 @@ void CheckOther::zerodivError(const Token *tok)
reportError(tok, Severity::error, "zerodiv", "Division by zero.");
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
/** @brief Check for NaN (not-a-number) in an arithmetic expression
* @note e.g. double d = 1.0 / 0.0 + 100.0;
*/
void CheckOther::checkNanInArithmeticExpression()
{
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
if (Token::Match(tok, "inf.0 +|-") ||
Token::Match(tok, "+|- inf.0") ||
Token::Match(tok, "+|- %num% / 0.0")) {
nanInArithmeticExpressionError(tok);
}
}
}
void CheckOther::nanInArithmeticExpressionError(const Token *tok)
{
reportError(tok, Severity::style, "nanInArithmeticExpression",
"Using NaN/Inf in a computation.\n"
"Although nothing bad really happens, it is suspicious.");
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void CheckOther::checkMathFunctions()

View File

@ -72,6 +72,7 @@ public:
checkOther.checkIncompleteArrayFill();
checkOther.checkSuspiciousStringCompare();
checkOther.checkVarFuncNullUB();
checkOther.checkNanInArithmeticExpression();
}
/** @brief Run checks against the simplified token list */
@ -158,6 +159,9 @@ public:
/** @brief %Check zero division*/
void checkZeroDivision();
/** @brief Check for NaN (not-a-number) in an arithmetic expression */
void checkNanInArithmeticExpression();
/** @brief %Check for parameters given to math function that do not make sense*/
void checkMathFunctions();
@ -278,6 +282,7 @@ private:
void variableScopeError(const Token *tok, const std::string &varname);
void strPlusCharError(const Token *tok);
void zerodivError(const Token *tok);
void nanInArithmeticExpressionError(const Token *tok);
void mathfunctionCallError(const Token *tok, const unsigned int numParam = 1);
void cctypefunctionCallError(const Token *tok, const std::string &functionName, const std::string &value);
void redundantAssignmentError(const Token *tok1, const Token* tok2, const std::string& var, bool inconclusive);
@ -377,6 +382,7 @@ private:
c.moduloAlwaysTrueFalseError(0, "1");
c.incompleteArrayFillError(0, "buffer", "memset", false);
c.varFuncNullUBError(0);
c.nanInArithmeticExpressionError(0);
}
static std::string myName() {
@ -438,7 +444,8 @@ private:
"* Comparisons of modulo results that are always true/false.\n"
"* Array filled incompletely using memset/memcpy/memmove.\n"
"* redundant get and set function of user id (--std=posix).\n"
"* Passing NULL pointer to function with variable number of arguments leads to UB on some platforms.\n";
"* Passing NULL pointer to function with variable number of arguments leads to UB on some platforms.\n"
"* NaN (not a number) value used in arithmetic expression.\n";
}
void checkExpressionRange(const std::list<const Function*> &constFunctions,

View File

@ -43,6 +43,8 @@ private:
TEST_CASE(zeroDiv5);
TEST_CASE(zeroDiv6);
TEST_CASE(nanInArithmeticExpression);
TEST_CASE(sprintf1); // Dangerous usage of sprintf
TEST_CASE(sprintf2);
TEST_CASE(sprintf3);
@ -410,6 +412,47 @@ private:
ASSERT_EQUALS("[test.cpp:3]: (error) Division by zero.\n", errout.str());
}
void nanInArithmeticExpression() {
check("void f()\n"
"{\n"
" double x = 3.0 / 0.0 + 1.0\n"
" printf(\"%f\n\", x);\n"
"}");
ASSERT_EQUALS(
"[test.cpp:3]: (style) Using NaN/Inf in a computation.\n", errout.str());
check("void f()\n"
"{\n"
" double x = 3.0 / 0.0 - 1.0\n"
" printf(\"%f\n\", x);\n"
"}");
ASSERT_EQUALS(
"[test.cpp:3]: (style) Using NaN/Inf in a computation.\n", errout.str());
check("void f()\n"
"{\n"
" double x = 1.0 + 3.0 / 0.0\n"
" printf(\"%f\n\", x);\n"
"}");
ASSERT_EQUALS(
"[test.cpp:3]: (style) Using NaN/Inf in a computation.\n", errout.str());
check("void f()\n"
"{\n"
" double x = 1.0 - 3.0 / 0.0\n"
" printf(\"%f\n\", x);\n"
"}");
ASSERT_EQUALS(
"[test.cpp:3]: (style) Using NaN/Inf in a computation.\n", errout.str());
check("void f()\n"
"{\n"
" double x = 3.0 / 0.0\n"
" printf(\"%f\n\", x);\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void sprintfUsage(const char code[]) {
// Clear the error buffer..