Fixed #1748 (Undefined Behavior: Modification of string literal)
This commit is contained in:
parent
70a1e11ada
commit
9d31afb663
|
@ -29,6 +29,30 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// Writing string literal is UB
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
void CheckString::stringLiteralWrite()
|
||||||
|
{
|
||||||
|
for (const Token* tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||||
|
if (!tok->variable())
|
||||||
|
continue;
|
||||||
|
const Token *str = tok->getValueTokenMinStrSize();
|
||||||
|
if (!str)
|
||||||
|
continue;
|
||||||
|
if (Token::Match(tok, "%var% [") && Token::Match(tok->linkAt(1), "] ="))
|
||||||
|
stringLiteralWriteError(tok);
|
||||||
|
else if (Token::Match(tok->previous(), "* %var% ="))
|
||||||
|
stringLiteralWriteError(tok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckString::stringLiteralWriteError(const Token *tok)
|
||||||
|
{
|
||||||
|
reportError(tok, Severity::error, "stringLiteralWrite",
|
||||||
|
"Modifying string literal directly or indirectly is UB");
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// Check for string comparison involving two static strings.
|
// Check for string comparison involving two static strings.
|
||||||
// if(strcmp("00FF00","00FF00")==0) // <- statement is always true
|
// if(strcmp("00FF00","00FF00")==0) // <- statement is always true
|
||||||
|
|
|
@ -59,8 +59,12 @@ public:
|
||||||
checkString.checkIncorrectStringCompare();
|
checkString.checkIncorrectStringCompare();
|
||||||
checkString.checkAlwaysTrueOrFalseStringCompare();
|
checkString.checkAlwaysTrueOrFalseStringCompare();
|
||||||
checkString.sprintfOverlappingData();
|
checkString.sprintfOverlappingData();
|
||||||
|
checkString.stringLiteralWrite();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @brief undefined behaviour, writing string literal */
|
||||||
|
void stringLiteralWrite();
|
||||||
|
|
||||||
/** @brief str plus char (unusual pointer arithmetic) */
|
/** @brief str plus char (unusual pointer arithmetic) */
|
||||||
void strPlusChar();
|
void strPlusChar();
|
||||||
|
|
||||||
|
@ -77,6 +81,7 @@ public:
|
||||||
void sprintfOverlappingData();
|
void sprintfOverlappingData();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void stringLiteralWriteError(const Token *tok);
|
||||||
void sprintfOverlappingDataError(const Token *tok, const std::string &varname);
|
void sprintfOverlappingDataError(const Token *tok, const std::string &varname);
|
||||||
void strPlusCharError(const Token *tok);
|
void strPlusCharError(const Token *tok);
|
||||||
void incorrectStringCompareError(const Token *tok, const std::string& func, const std::string &string);
|
void incorrectStringCompareError(const Token *tok, const std::string& func, const std::string &string);
|
||||||
|
|
|
@ -32,6 +32,8 @@ public:
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void run() {
|
void run() {
|
||||||
|
TEST_CASE(stringLiteralWrite);
|
||||||
|
|
||||||
TEST_CASE(alwaysTrueFalseStringCompare);
|
TEST_CASE(alwaysTrueFalseStringCompare);
|
||||||
TEST_CASE(suspiciousStringCompare);
|
TEST_CASE(suspiciousStringCompare);
|
||||||
TEST_CASE(suspiciousStringCompare_char);
|
TEST_CASE(suspiciousStringCompare_char);
|
||||||
|
@ -95,6 +97,26 @@ private:
|
||||||
checkString.checkAlwaysTrueOrFalseStringCompare();
|
checkString.checkAlwaysTrueOrFalseStringCompare();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void stringLiteralWrite() {
|
||||||
|
check("void f() {\n"
|
||||||
|
" char *abc = \"abc\";\n"
|
||||||
|
" abc[0] = 'a';\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (error) Modifying string literal directly or indirectly is UB\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" char *abc = \"abc\";\n"
|
||||||
|
" *abc = 'a';\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (error) Modifying string literal directly or indirectly is UB\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" char *abc = \"abc\";\n"
|
||||||
|
" if (*abc == 'a'){}\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void alwaysTrueFalseStringCompare() {
|
void alwaysTrueFalseStringCompare() {
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" if (strcmp(\"A\",\"A\")){}\n"
|
" if (strcmp(\"A\",\"A\")){}\n"
|
||||||
|
|
Loading…
Reference in New Issue