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:
parent
3bdcf68990
commit
644a216394
|
@ -1464,21 +1464,10 @@ void CheckBufferOverrun::checkStructVariable()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
void CheckBufferOverrun::bufferOverrun()
|
void CheckBufferOverrun::bufferOverrun()
|
||||||
{
|
|
||||||
checkGlobalAndLocalVariable();
|
|
||||||
if (_tokenizer->isMaxTime())
|
|
||||||
return;
|
|
||||||
checkStructVariable();
|
|
||||||
checkBufferAllocatedWithStrlen();
|
|
||||||
checkStringArgument();
|
|
||||||
checkInsecureCmdLineArgs();
|
|
||||||
}
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void CheckBufferOverrun::bufferOverrun2()
|
|
||||||
{
|
{
|
||||||
// singlepass checking using ast, symboldatabase and valueflow
|
// singlepass checking using ast, symboldatabase and valueflow
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||||
|
|
|
@ -61,17 +61,24 @@ public:
|
||||||
|
|
||||||
void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) {
|
void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) {
|
||||||
CheckBufferOverrun checkBufferOverrun(tokenizer, settings, errorLogger);
|
CheckBufferOverrun checkBufferOverrun(tokenizer, settings, errorLogger);
|
||||||
|
checkBufferOverrun.checkGlobalAndLocalVariable();
|
||||||
|
if (_tokenizer->isMaxTime())
|
||||||
|
return;
|
||||||
|
checkBufferOverrun.checkStructVariable();
|
||||||
|
checkBufferOverrun.checkBufferAllocatedWithStrlen();
|
||||||
|
checkBufferOverrun.checkInsecureCmdLineArgs();
|
||||||
checkBufferOverrun.bufferOverrun();
|
checkBufferOverrun.bufferOverrun();
|
||||||
checkBufferOverrun.bufferOverrun2();
|
|
||||||
checkBufferOverrun.arrayIndexThenCheck();
|
checkBufferOverrun.arrayIndexThenCheck();
|
||||||
checkBufferOverrun.negativeArraySize();
|
checkBufferOverrun.negativeArraySize();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief %Check for buffer overruns */
|
void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) {
|
||||||
void bufferOverrun();
|
CheckBufferOverrun checkBufferOverrun(tokenizer, settings, errorLogger);
|
||||||
|
checkBufferOverrun.checkStringArgument();
|
||||||
|
}
|
||||||
|
|
||||||
/** @brief %Check for buffer overruns #2 (single pass, use ast and valueflow) */
|
/** @brief %Check for buffer overruns (single pass, use ast and valueflow) */
|
||||||
void bufferOverrun2();
|
void bufferOverrun();
|
||||||
|
|
||||||
/** @brief Using array index before bounds check */
|
/** @brief Using array index before bounds check */
|
||||||
void arrayIndexThenCheck();
|
void arrayIndexThenCheck();
|
||||||
|
|
|
@ -49,6 +49,7 @@ public:
|
||||||
// Checks
|
// Checks
|
||||||
checkString.strPlusChar();
|
checkString.strPlusChar();
|
||||||
checkString.checkSuspiciousStringCompare();
|
checkString.checkSuspiciousStringCompare();
|
||||||
|
checkString.stringLiteralWrite();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief Run checks against the simplified token list */
|
/** @brief Run checks against the simplified token list */
|
||||||
|
@ -59,7 +60,6 @@ public:
|
||||||
checkString.checkIncorrectStringCompare();
|
checkString.checkIncorrectStringCompare();
|
||||||
checkString.checkAlwaysTrueOrFalseStringCompare();
|
checkString.checkAlwaysTrueOrFalseStringCompare();
|
||||||
checkString.sprintfOverlappingData();
|
checkString.sprintfOverlappingData();
|
||||||
checkString.stringLiteralWrite();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief undefined behaviour, writing string literal */
|
/** @brief undefined behaviour, writing string literal */
|
||||||
|
|
|
@ -54,16 +54,15 @@ private:
|
||||||
Tokenizer tokenizer(&settings, this);
|
Tokenizer tokenizer(&settings, this);
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
tokenizer.tokenize(istr, filename);
|
tokenizer.tokenize(istr, filename);
|
||||||
tokenizer.simplifyTokenList2();
|
|
||||||
|
|
||||||
// Clear the error buffer..
|
// Clear the error buffer..
|
||||||
errout.str("");
|
errout.str("");
|
||||||
|
|
||||||
// Check for buffer overruns..
|
// Check for buffer overruns..
|
||||||
CheckBufferOverrun checkBufferOverrun(&tokenizer, &settings, this);
|
CheckBufferOverrun checkBufferOverrun(&tokenizer, &settings, this);
|
||||||
checkBufferOverrun.bufferOverrun();
|
checkBufferOverrun.runChecks(&tokenizer, &settings, this);
|
||||||
checkBufferOverrun.bufferOverrun2();
|
tokenizer.simplifyTokenList2();
|
||||||
checkBufferOverrun.arrayIndexThenCheck();
|
checkBufferOverrun.runSimplifiedChecks(&tokenizer, &settings, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void run() {
|
void run() {
|
||||||
|
@ -2001,6 +2000,13 @@ private:
|
||||||
" if ( name[0] == 'U' ? name[1] : 0) {}\n"
|
" if ( name[0] == 'U' ? name[1] : 0) {}\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
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() {
|
void array_index_same_struct_and_var_name() {
|
||||||
|
|
|
@ -88,6 +88,24 @@ private:
|
||||||
" abc[0] = 'a';\n"
|
" abc[0] = 'a';\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
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() {
|
void alwaysTrueFalseStringCompare() {
|
||||||
|
|
Loading…
Reference in New Issue