Fixed #959 (new check: wrong usage of fflush())

This commit is contained in:
Zachary Blair 2010-05-03 23:14:45 -07:00
parent 804b2a0952
commit 707d27f3d8
3 changed files with 48 additions and 1 deletions

View File

@ -254,6 +254,19 @@ void CheckOther::checkEmptyStringTest()
} }
} }
} }
//---------------------------------------------------------------------------
// fflush(stdin) <- fflush only applies to output streams in ANSI C
//---------------------------------------------------------------------------
void CheckOther::checkFflushOnInputStream()
{
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
{
if (Token::Match(tok, "fflush ( stdin )"))
{
fflushOnInputStreamError(tok, tok->strAt(2));
}
}
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// strtol(str, 0, radix) <- radix must be 0 or 2-36 // strtol(str, 0, radix) <- radix must be 0 or 2-36
@ -3502,3 +3515,9 @@ void CheckOther::emptyStringTestError(const Token *tok, const std::string &var_n
"emptyStringTest", "Non-empty string test can be simplified to \"*" + var_name + " != '\\0'\""); "emptyStringTest", "Non-empty string test can be simplified to \"*" + var_name + " != '\\0'\"");
} }
} }
void CheckOther::fflushOnInputStreamError(const Token *tok, const std::string &varname)
{
reportError(tok, Severity::possibleError,
"fflushOnInputStream", "fflush() called on input stream \"" + varname + "\" may result in undefined behaviour");
}

View File

@ -77,6 +77,7 @@ public:
checkOther.invalidFunctionUsage(); checkOther.invalidFunctionUsage();
checkOther.checkZeroDivision(); checkOther.checkZeroDivision();
checkOther.checkMathFunctions(); checkOther.checkMathFunctions();
checkOther.checkFflushOnInputStream();
// New type of check: Check execution paths // New type of check: Check execution paths
checkOther.executionPaths(); checkOther.executionPaths();
@ -158,6 +159,9 @@ public:
/** @brief %Check for inefficient empty string test*/ /** @brief %Check for inefficient empty string test*/
void checkEmptyStringTest(); void checkEmptyStringTest();
/** @brief %Check for using fflush() on an input stream*/
void checkFflushOnInputStream();
// Error messages.. // Error messages..
void cstyleCastError(const Token *tok); void cstyleCastError(const Token *tok);
void redundantIfDelete0Error(const Token *tok); void redundantIfDelete0Error(const Token *tok);
@ -184,6 +188,7 @@ public:
void mathfunctionCallError(const Token *tok, const unsigned int numParam = 1); void mathfunctionCallError(const Token *tok, const unsigned int numParam = 1);
void postIncrementError(const Token *tok, const std::string &var_name, const bool isIncrement); void postIncrementError(const Token *tok, const std::string &var_name, const bool isIncrement);
void emptyStringTestError(const Token *tok, const std::string &var_name, const bool isTestForEmpty); void emptyStringTestError(const Token *tok, const std::string &var_name, const bool isTestForEmpty);
void fflushOnInputStreamError(const Token *tok, const std::string &varname);
void getErrorMessages() void getErrorMessages()
{ {
@ -196,6 +201,7 @@ public:
uninitvarError(0, "varname"); uninitvarError(0, "varname");
zerodivError(0); zerodivError(0);
mathfunctionCallError(0); mathfunctionCallError(0);
fflushOnInputStreamError(0, "stdin");
// style // style
cstyleCastError(0); cstyleCastError(0);
@ -232,6 +238,9 @@ public:
"* null pointer dereferencing\n" "* null pointer dereferencing\n"
"* using uninitialized variables and data\n" "* using uninitialized variables and data\n"
// possible error
"* using fflush() on an input stream\n"
// style // style
"* C-style pointer cast in cpp file\n" "* C-style pointer cast in cpp file\n"
"* redundant if\n" "* redundant if\n"
@ -246,7 +255,8 @@ public:
"* unusal pointer arithmetic. For example: \"abc\" + 'd'\n" "* unusal pointer arithmetic. For example: \"abc\" + 'd'\n"
// optimisations // optimisations
"* optimisation: detect post increment/decrement\n"; "* optimisation: detect post increment/decrement\n"
"* optimisation: simplify empty string tests\n";
} }
private: private:

View File

@ -92,6 +92,8 @@ private:
TEST_CASE(mathfunctionCall1); TEST_CASE(mathfunctionCall1);
TEST_CASE(emptyStringTest); TEST_CASE(emptyStringTest);
TEST_CASE(fflushOnInputStreamTest);
} }
void check(const char code[]) void check(const char code[])
@ -115,6 +117,7 @@ private:
checkOther.checkZeroDivision(); checkOther.checkZeroDivision();
checkOther.checkMathFunctions(); checkOther.checkMathFunctions();
checkOther.checkEmptyStringTest(); checkOther.checkEmptyStringTest();
checkOther.checkFflushOnInputStream();
} }
@ -2471,6 +2474,21 @@ private:
check("if (0 < strlen(str)) { }"); check("if (0 < strlen(str)) { }");
ASSERT_EQUALS("[test.cpp:1]: (possible style) Non-empty string test can be simplified to \"*str != '\\0'\"\n", errout.str()); ASSERT_EQUALS("[test.cpp:1]: (possible style) Non-empty string test can be simplified to \"*str != '\\0'\"\n", errout.str());
} }
void fflushOnInputStreamTest()
{
check("void foo()\n"
"{\n"
" fflush(stdin);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (possible error) fflush() called on input stream \"stdin\" may result in undefined behaviour\n", errout.str());
check("void foo()\n"
"{\n"
" fflush(stdout);\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
}; };
REGISTER_TEST(TestOther) REGISTER_TEST(TestOther)