Fixed #959 (new check: wrong usage of fflush())
This commit is contained in:
parent
804b2a0952
commit
707d27f3d8
|
@ -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");
|
||||||
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue