Fixed two false positives related to char arrays initialized by a literal:

- Run check for writing to string literals on non-simplified token list (#7283)
- Run buffer overrun checking for string literals on non-simplified token list (https://sourceforge.net/p/cppcheck/discussion/general/thread/2c33dfc5/)
This commit is contained in:
PKEuS 2016-07-07 19:38:15 +02:00
parent 3bdcf68990
commit 644a216394
5 changed files with 42 additions and 22 deletions

View File

@ -1464,21 +1464,10 @@ void CheckBufferOverrun::checkStructVariable()
}
}
}
//---------------------------------------------------------------------------
void CheckBufferOverrun::bufferOverrun()
{
checkGlobalAndLocalVariable();
if (_tokenizer->isMaxTime())
return;
checkStructVariable();
checkBufferAllocatedWithStrlen();
checkStringArgument();
checkInsecureCmdLineArgs();
}
//---------------------------------------------------------------------------
void CheckBufferOverrun::bufferOverrun2()
{
// singlepass checking using ast, symboldatabase and valueflow
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {

View File

@ -61,17 +61,24 @@ public:
void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) {
CheckBufferOverrun checkBufferOverrun(tokenizer, settings, errorLogger);
checkBufferOverrun.checkGlobalAndLocalVariable();
if (_tokenizer->isMaxTime())
return;
checkBufferOverrun.checkStructVariable();
checkBufferOverrun.checkBufferAllocatedWithStrlen();
checkBufferOverrun.checkInsecureCmdLineArgs();
checkBufferOverrun.bufferOverrun();
checkBufferOverrun.bufferOverrun2();
checkBufferOverrun.arrayIndexThenCheck();
checkBufferOverrun.negativeArraySize();
}
/** @brief %Check for buffer overruns */
void bufferOverrun();
void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) {
CheckBufferOverrun checkBufferOverrun(tokenizer, settings, errorLogger);
checkBufferOverrun.checkStringArgument();
}
/** @brief %Check for buffer overruns #2 (single pass, use ast and valueflow) */
void bufferOverrun2();
/** @brief %Check for buffer overruns (single pass, use ast and valueflow) */
void bufferOverrun();
/** @brief Using array index before bounds check */
void arrayIndexThenCheck();

View File

@ -49,6 +49,7 @@ public:
// Checks
checkString.strPlusChar();
checkString.checkSuspiciousStringCompare();
checkString.stringLiteralWrite();
}
/** @brief Run checks against the simplified token list */
@ -59,7 +60,6 @@ public:
checkString.checkIncorrectStringCompare();
checkString.checkAlwaysTrueOrFalseStringCompare();
checkString.sprintfOverlappingData();
checkString.stringLiteralWrite();
}
/** @brief undefined behaviour, writing string literal */

View File

@ -54,16 +54,15 @@ private:
Tokenizer tokenizer(&settings, this);
std::istringstream istr(code);
tokenizer.tokenize(istr, filename);
tokenizer.simplifyTokenList2();
// Clear the error buffer..
errout.str("");
// Check for buffer overruns..
CheckBufferOverrun checkBufferOverrun(&tokenizer, &settings, this);
checkBufferOverrun.bufferOverrun();
checkBufferOverrun.bufferOverrun2();
checkBufferOverrun.arrayIndexThenCheck();
checkBufferOverrun.runChecks(&tokenizer, &settings, this);
tokenizer.simplifyTokenList2();
checkBufferOverrun.runSimplifiedChecks(&tokenizer, &settings, this);
}
void run() {
@ -2001,6 +2000,13 @@ private:
" if ( name[0] == 'U' ? name[1] : 0) {}\n"
"}");
ASSERT_EQUALS("", errout.str());
check("int main(int argc, char **argv) {\n"
" char str[6] = \"\\0\";\n"
" unsigned short port = 65535;\n"
" snprintf(str, sizeof(str), \"%hu\", port);\n"
"}", settings0, "test.c");
ASSERT_EQUALS("", errout.str());
}
void array_index_same_struct_and_var_name() {

View File

@ -88,6 +88,24 @@ private:
" abc[0] = 'a';\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo_FP1(char *p) {\n"
" p[1] = 'B';\n"
"}\n"
"void foo_FP2(void) {\n"
" char* s = \"Y\";\n"
" foo_FP1(s);\n"
"}");
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:5]: (error) Modifying string literal \"Y\" directly or indirectly is undefined behaviour.\n", errout.str());
check("void foo_FP1(char *p) {\n"
" p[1] = 'B';\n"
"}\n"
"void foo_FP2(void) {\n"
" char s[10] = \"Y\";\n"
" foo_FP1(s);\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void alwaysTrueFalseStringCompare() {