Fixed #4920 (Microsoft ATL/MFC CString::Format argument checking)

This commit is contained in:
Robert Reif 2013-09-26 16:20:01 +02:00 committed by Daniel Marjamäki
parent 2de3ebcb1e
commit 44d86e97c0
3 changed files with 44 additions and 1 deletions

View File

@ -407,6 +407,7 @@ void CheckIO::checkWrongPrintfScanfArguments()
{
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
bool warning = _settings->isEnabled("warning");
bool windows = _settings->isWindowsPlatform();
std::size_t functions = symbolDatabase->functionScopes.size();
for (std::size_t j = 0; j < functions; ++j) {
@ -437,7 +438,11 @@ void CheckIO::checkWrongPrintfScanfArguments()
if (!formatString.empty()) {
/* formatstring found in library */
} else if (Token::Match(tok, "printf|scanf|wprintf|wscanf ( %str%")) {
} else if (Token::Match(tok, "printf|scanf|wprintf|wscanf ( %str%") ||
(windows && (Token::Match(tok, "Format|AppendFormat ( %str%") &&
Token::Match(tok->tokAt(-2), "%var% .") && tok->tokAt(-2)->variable() &&
tok->tokAt(-2)->variable()->typeStartToken()->str() == "CString"))) {
formatString = tok->strAt(2);
if (tok->strAt(3) == ",") {
argListTok = tok->tokAt(4);

View File

@ -240,6 +240,16 @@ public:
/** set the platform type for user specified platforms */
bool platformFile(const std::string &filename);
/**
* @brief Returns true if platform type is Windows
* @return true if Windows platform type.
*/
bool isWindowsPlatform() const {
return platformType == Win32A ||
platformType == Win32W ||
platformType == Win64;
}
};
/// @}

View File

@ -49,6 +49,7 @@ private:
TEST_CASE(testPosixPrintfScanfParameterPosition); // #4900
TEST_CASE(testMicrosoftPrintfArgument); // ticket #4902
TEST_CASE(testMicrosoftCStringFormatArguments); // ticket #4920
TEST_CASE(testlibrarycfg); // library configuration
}
@ -2132,6 +2133,33 @@ private:
"[test.cpp:17]: (warning) 'I64' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n", errout.str());
}
void testMicrosoftCStringFormatArguments() { // ticket #4920
check("void foo() {\n"
" unsigned __int32 u32;\n"
" String string;\n"
" string.Format(\"%I32d\", u32);\n"
" string.AppendFormat(\"%I32d\", u32);\n"
"}", false, false, Settings::Win32A);
ASSERT_EQUALS("", errout.str());
check("void foo() {\n"
" unsigned __int32 u32;\n"
" CString string;\n"
" string.Format(\"%I32d\", u32);\n"
" string.AppendFormat(\"%I32d\", u32);\n"
"}", false, false, Settings::Unix32);
ASSERT_EQUALS("", errout.str());
check("void foo() {\n"
" unsigned __int32 u32;\n"
" CString string;\n"
" string.Format(\"%I32d\", u32);\n"
" string.AppendFormat(\"%I32d\", u32);\n"
"}", false, false, Settings::Win32A);
ASSERT_EQUALS("[test.cpp:4]: (warning) %I32d in format string (no. 1) requires a signed integer but the argument type is 'unsigned __int32 {aka unsigned int}'.\n"
"[test.cpp:5]: (warning) %I32d in format string (no. 1) requires a signed integer but the argument type is 'unsigned __int32 {aka unsigned int}'.\n", errout.str());
}
void testlibrarycfg() {
const char code[] = "void f() {\n"
" format(\"%s\");\n"