Fixed #886 (new check: wrong value passed to isgraph function)

This commit is contained in:
Marek Zmysłowski 2011-11-17 16:31:16 +01:00 committed by Daniel Marjamäki
parent 68a1b69d32
commit 994f08fdf0
3 changed files with 159 additions and 2 deletions

View File

@ -2027,7 +2027,6 @@ void CheckOther::checkMathFunctions()
MathLib::isNegative(tok->strAt(4))) {
mathfunctionCallError(tok, 2);
}
}
}
@ -2041,7 +2040,22 @@ void CheckOther::mathfunctionCallError(const Token *tok, const unsigned int numP
} else
reportError(tok, Severity::error, "wrongmathcall", "Passing value " " to " "() leads to undefined result");
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void CheckOther::checkCCTypeFunctions()
{
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
if (tok->varId() == 0 &&
Token::Match(tok, "isalnum|isalpha|iscntrl|isdigit|isgraph|islower|isprint|ispunct|isspace|isupper|isxdigit ( %num% )") &&
MathLib::isNegative(tok->strAt(2))) {
cctypefunctionCallError(tok, tok->str(), tok->tokAt(2)->str());
}
}
}
void CheckOther::cctypefunctionCallError(const Token *tok, const std::string &functionName, const std::string &value)
{
reportError(tok, Severity::error, "wrongcctypecall", "Passing value " + value + " to " + functionName + "() cause undefined behavior, which may lead to a crash");
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
/** Is there a function with given name? */

View File

@ -87,6 +87,7 @@ public:
checkOther.invalidFunctionUsage();
checkOther.checkZeroDivision();
checkOther.checkMathFunctions();
checkOther.checkCCTypeFunctions();
checkOther.checkFflushOnInputStream();
checkOther.invalidScanf();
checkOther.checkWrongPrintfScanfArguments();
@ -151,6 +152,9 @@ public:
/** @brief %Check for parameters given to math function that do not make sense*/
void checkMathFunctions();
/** @brief %Check for parameters given to cctype function that do make error*/
void checkCCTypeFunctions();
void lookupVar(const Token *tok1, const std::string &varname);
/** @brief %Check for using fflush() on an input stream*/
@ -264,6 +268,7 @@ public:
void zerodivError(const Token *tok);
void coutCerrMisusageError(const Token* tok, const std::string& streamName);
void mathfunctionCallError(const Token *tok, const unsigned int numParam = 1);
void cctypefunctionCallError(const Token *tok, const std::string &functionName, const std::string &value);
void fflushOnInputStreamError(const Token *tok, const std::string &varname);
void redundantAssignmentInSwitchError(const Token *tok, const std::string &varname);
void redundantStrcpyInSwitchError(const Token *tok, const std::string &varname);
@ -349,6 +354,7 @@ public:
c.comparisonOfBoolExpressionWithIntError(0);
c.SuspiciousSemicolonError(0);
c.wrongPrintfScanfArgumentsError(0,"printf",3,2);
c.cctypefunctionCallError(0, "funname", "value");
}
std::string myName() const {
@ -402,6 +408,7 @@ public:
"* testing is unsigned variable is positive\n"
"* using bool in bitwise expression\n"
"* Suspicious use of ; at the end of 'if/for/while' statement.\n"
"* incorrect usage of functions from ctype library.\n"
// optimisations
"* optimisation: detect post increment/decrement\n";

View File

@ -71,6 +71,7 @@ private:
TEST_CASE(passedByValue);
TEST_CASE(mathfunctionCall1);
TEST_CASE(cctypefunctionCall);
TEST_CASE(fflushOnInputStreamTest);
@ -1030,6 +1031,141 @@ private:
}
void cctypefunctionCall() {
// isalnum
check("void foo()\n"
"{\n"
" std::cout << isalnum(61) << std::endl;\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo()\n"
"{\n"
" std::cout << isalnum(-61) << std::endl;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -61 to isalnum() cause undefined behavior, which may lead to a crash\n", errout.str());
check("void foo()\n"
"{\n"
" std::cout << isalpha(61) << std::endl;\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo()\n"
"{\n"
" std::cout << isalpha(-61) << std::endl;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -61 to isalpha() cause undefined behavior, which may lead to a crash\n", errout.str());
check("void foo()\n"
"{\n"
" std::cout << iscntrl(61) << std::endl;\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo()\n"
"{\n"
" std::cout << iscntrl(-61) << std::endl;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -61 to iscntrl() cause undefined behavior, which may lead to a crash\n", errout.str());
check("void foo()\n"
"{\n"
" std::cout << isdigit(61) << std::endl;\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo()\n"
"{\n"
" std::cout << isdigit(-61) << std::endl;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -61 to isdigit() cause undefined behavior, which may lead to a crash\n", errout.str());
check("void foo()\n"
"{\n"
" std::cout << isgraph(61) << std::endl;\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo()\n"
"{\n"
" std::cout << isgraph(-61) << std::endl;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -61 to isgraph() cause undefined behavior, which may lead to a crash\n", errout.str());
check("void foo()\n"
"{\n"
" std::cout << islower(61) << std::endl;\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo()\n"
"{\n"
" std::cout << islower(-61) << std::endl;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -61 to islower() cause undefined behavior, which may lead to a crash\n", errout.str());
check("void foo()\n"
"{\n"
" std::cout << isprint(61) << std::endl;\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo()\n"
"{\n"
" std::cout << isprint(-61) << std::endl;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -61 to isprint() cause undefined behavior, which may lead to a crash\n", errout.str());
check("void foo()\n"
"{\n"
" std::cout << ispunct(61) << std::endl;\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo()\n"
"{\n"
" std::cout << ispunct(-61) << std::endl;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -61 to ispunct() cause undefined behavior, which may lead to a crash\n", errout.str());
check("void foo()\n"
"{\n"
" std::cout << isspace(61) << std::endl;\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo()\n"
"{\n"
" std::cout << isspace(-61) << std::endl;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -61 to isspace() cause undefined behavior, which may lead to a crash\n", errout.str());
check("void foo()\n"
"{\n"
" std::cout << isupper(61) << std::endl;\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo()\n"
"{\n"
" std::cout << isupper(-61) << std::endl;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -61 to isupper() cause undefined behavior, which may lead to a crash\n", errout.str());
check("void foo()\n"
"{\n"
" std::cout << isxdigit(61) << std::endl;\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo()\n"
"{\n"
" std::cout << isxdigit(-61) << std::endl;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -61 to isxdigit() cause undefined behavior, which may lead to a crash\n", errout.str());
}
void fflushOnInputStreamTest() {
check("void foo()\n"
"{\n"