This patch adds pointer to format string support to printf. Ticket: #5051

This commit is contained in:
Robert Reif 2013-10-05 07:47:52 +02:00 committed by Daniel Marjamäki
parent 44559a1fb2
commit 5dbc02250f
2 changed files with 31 additions and 12 deletions

View File

@ -477,24 +477,24 @@ void CheckIO::checkWrongPrintfScanfArguments()
if (formatStringTok) { if (formatStringTok) {
/* formatstring found in library */ /* formatstring found in library */
} else if (Token::Match(tok, "printf|scanf|wprintf|wscanf ( %str%") || } else if (Token::Match(tok, "printf|scanf|wprintf|wscanf (") ||
(windows && (Token::Match(tok, "printf_s|wprintf_s|scanf_s|wscanf_s ( %str%") || (windows && (Token::Match(tok, "printf_s|wprintf_s|scanf_s|wscanf_s (") ||
(Token::Match(tok, "Format|AppendFormat ( %str%") && (Token::Match(tok, "Format|AppendFormat (") &&
Token::Match(tok->tokAt(-2), "%var% .") && tok->tokAt(-2)->variable() && Token::Match(tok->tokAt(-2), "%var% .") && tok->tokAt(-2)->variable() &&
tok->tokAt(-2)->variable()->typeStartToken()->str() == "CString")))) { tok->tokAt(-2)->variable()->typeStartToken()->str() == "CString")))) {
// Find first parameter and format string // Find second parameter and format string
if (!findFormat(0, tok->tokAt(2), &formatStringTok, &argListTok)) if (!findFormat(0, tok->tokAt(2), &formatStringTok, &argListTok))
continue; continue;
} else if (Token::Match(tok, "sprintf|fprintf|sscanf|fscanf|swscanf|fwprintf|fwscanf ( %any%") || } else if (Token::Match(tok, "sprintf|fprintf|sscanf|fscanf|swscanf|fwprintf|fwscanf ( %any%") ||
(Token::simpleMatch(tok, "swprintf (") && Token::Match(tok->tokAt(2)->nextArgument(), "%str%")) || (Token::simpleMatch(tok, "swprintf (") && Token::Match(tok->tokAt(2)->nextArgument(), "%str%")) ||
(windows && Token::Match(tok, "sscanf_s|swscanf_s|fscanf_s|fwscanf_s|fprintf_s|fwprintf_s ( %any%"))) { (windows && Token::Match(tok, "sscanf_s|swscanf_s|fscanf_s|fwscanf_s|fprintf_s|fwprintf_s ( %any%"))) {
// Find second parameter and format string // Find third parameter and format string
if (!findFormat(1, tok->tokAt(2), &formatStringTok, &argListTok)) if (!findFormat(1, tok->tokAt(2), &formatStringTok, &argListTok))
continue; continue;
} else if (Token::Match(tok, "snprintf|fnprintf (") || } else if (Token::Match(tok, "snprintf|fnprintf (") ||
(windows && Token::Match(tok, "_snprintf|_snwprintf (")) || (windows && Token::Match(tok, "_snprintf|_snwprintf (")) ||
(Token::simpleMatch(tok, "swprintf (") && !Token::Match(tok->tokAt(2)->nextArgument(), "%str%"))) { (Token::simpleMatch(tok, "swprintf (") && !Token::Match(tok->tokAt(2)->nextArgument(), "%str%"))) {
// Find third parameter and format string // Find forth parameter and format string
if (!findFormat(2, tok->tokAt(2), &formatStringTok, &argListTok)) if (!findFormat(2, tok->tokAt(2), &formatStringTok, &argListTok))
continue; continue;
} else if (windows && Token::Match(tok, "sprintf_s|swprintf_s (")) { } else if (windows && Token::Match(tok, "sprintf_s|swprintf_s (")) {
@ -525,6 +525,8 @@ void CheckIO::checkWrongPrintfScanfArguments()
if (formatStringTok) if (formatStringTok)
formatString = formatStringTok->str(); formatString = formatStringTok->str();
else
continue;
// Count format string parameters.. // Count format string parameters..
bool scanf_s = windows ? Token::Match(tok, "scanf_s|wscanf_s|sscanf_s|swscanf_s|fscanf_s|fwscanf_s") : false; bool scanf_s = windows ? Token::Match(tok, "scanf_s|wscanf_s|sscanf_s|swscanf_s|fscanf_s|fwscanf_s") : false;

View File

@ -2414,13 +2414,30 @@ private:
check("void foo() {\n" check("void foo() {\n"
" const char * const format1 = \"%15s%17s%17s%17s%17s\n\";\n" " const char * const format1 = \"%15s%17s%17s%17s%17s\n\";\n"
" const char format2[] = \"%15s%17s%17s%17s%17s\n\";\n" " const char format2[] = \"%15s%17s%17s%17s%17s\n\";\n"
" const char * const format3 = format1;\n" " const char * const format3 = format1;\n" // we should warn about this someday
" sprintf_s(lineBuffer, format1, \"type\", \"sum\", \"avg\", \"min\", \"max\", 0);\n" " int i = 0;\n"
" sprintf_s(lineBuffer, format2, \"type\", \"sum\", \"avg\", \"min\", \"max\", 0);\n" " sprintf_s(lineBuffer, format1, \"type\", \"sum\", \"avg\", \"min\", i, 0);\n"
" sprintf_s(lineBuffer, format3, \"type\", \"sum\", \"avg\", \"min\", \"max\", 0);\n" " sprintf_s(lineBuffer, format2, \"type\", \"sum\", \"avg\", \"min\", i, 0);\n"
" sprintf_s(lineBuffer, format3, \"type\", \"sum\", \"avg\", \"min\", i, 0);\n"
" sprintf(lineBuffer, format1, \"type\", \"sum\", \"avg\", \"min\", i, 0);\n"
" sprintf(lineBuffer, format2, \"type\", \"sum\", \"avg\", \"min\", i, 0);\n"
" sprintf(lineBuffer, format3, \"type\", \"sum\", \"avg\", \"min\", i, 0);\n"
" printf(format1, \"type\", \"sum\", \"avg\", \"min\", i, 0);\n"
" printf(format2, \"type\", \"sum\", \"avg\", \"min\", i, 0);\n"
" printf(format3, \"type\", \"sum\", \"avg\", \"min\", i, 0);\n"
"}\n", false, false, Settings::Win32A); "}\n", false, false, Settings::Win32A);
ASSERT_EQUALS("[test.cpp:5]: (warning) sprintf_s format string requires 5 parameters but 6 are given.\n" ASSERT_EQUALS("[test.cpp:6]: (warning) %s in format string (no. 5) requires a char* given in the argument list.\n"
"[test.cpp:6]: (warning) sprintf_s format string requires 5 parameters but 6 are given.\n", errout.str()); "[test.cpp:6]: (warning) sprintf_s format string requires 5 parameters but 6 are given.\n"
"[test.cpp:7]: (warning) %s in format string (no. 5) requires a char* given in the argument list.\n"
"[test.cpp:7]: (warning) sprintf_s format string requires 5 parameters but 6 are given.\n"
"[test.cpp:9]: (warning) %s in format string (no. 5) requires a char* given in the argument list.\n"
"[test.cpp:9]: (warning) sprintf format string requires 5 parameters but 6 are given.\n"
"[test.cpp:10]: (warning) %s in format string (no. 5) requires a char* given in the argument list.\n"
"[test.cpp:10]: (warning) sprintf format string requires 5 parameters but 6 are given.\n"
"[test.cpp:12]: (warning) %s in format string (no. 5) requires a char* given in the argument list.\n"
"[test.cpp:12]: (warning) printf format string requires 5 parameters but 6 are given.\n"
"[test.cpp:13]: (warning) %s in format string (no. 5) requires a char* given in the argument list.\n"
"[test.cpp:13]: (warning) printf format string requires 5 parameters but 6 are given.\n", errout.str());
} }