diff --git a/lib/checkio.cpp b/lib/checkio.cpp index caee0efbe..568ac2416 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -477,24 +477,24 @@ void CheckIO::checkWrongPrintfScanfArguments() if (formatStringTok) { /* formatstring found in library */ - } else if (Token::Match(tok, "printf|scanf|wprintf|wscanf ( %str%") || - (windows && (Token::Match(tok, "printf_s|wprintf_s|scanf_s|wscanf_s ( %str%") || - (Token::Match(tok, "Format|AppendFormat ( %str%") && + } else if (Token::Match(tok, "printf|scanf|wprintf|wscanf (") || + (windows && (Token::Match(tok, "printf_s|wprintf_s|scanf_s|wscanf_s (") || + (Token::Match(tok, "Format|AppendFormat (") && Token::Match(tok->tokAt(-2), "%var% .") && tok->tokAt(-2)->variable() && 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)) continue; } else if (Token::Match(tok, "sprintf|fprintf|sscanf|fscanf|swscanf|fwprintf|fwscanf ( %any%") || (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%"))) { - // Find second parameter and format string + // Find third parameter and format string if (!findFormat(1, tok->tokAt(2), &formatStringTok, &argListTok)) continue; } else if (Token::Match(tok, "snprintf|fnprintf (") || (windows && Token::Match(tok, "_snprintf|_snwprintf (")) || (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)) continue; } else if (windows && Token::Match(tok, "sprintf_s|swprintf_s (")) { @@ -525,6 +525,8 @@ void CheckIO::checkWrongPrintfScanfArguments() if (formatStringTok) formatString = formatStringTok->str(); + else + continue; // Count format string parameters.. bool scanf_s = windows ? Token::Match(tok, "scanf_s|wscanf_s|sscanf_s|swscanf_s|fscanf_s|fwscanf_s") : false; diff --git a/test/testio.cpp b/test/testio.cpp index 116d3d28e..0b8b915a8 100644 --- a/test/testio.cpp +++ b/test/testio.cpp @@ -2414,13 +2414,30 @@ private: check("void foo() {\n" " const char * const format1 = \"%15s%17s%17s%17s%17s\n\";\n" " const char format2[] = \"%15s%17s%17s%17s%17s\n\";\n" - " const char * const format3 = format1;\n" - " sprintf_s(lineBuffer, format1, \"type\", \"sum\", \"avg\", \"min\", \"max\", 0);\n" - " sprintf_s(lineBuffer, format2, \"type\", \"sum\", \"avg\", \"min\", \"max\", 0);\n" - " sprintf_s(lineBuffer, format3, \"type\", \"sum\", \"avg\", \"min\", \"max\", 0);\n" + " const char * const format3 = format1;\n" // we should warn about this someday + " int i = 0;\n" + " sprintf_s(lineBuffer, format1, \"type\", \"sum\", \"avg\", \"min\", i, 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); - ASSERT_EQUALS("[test.cpp:5]: (warning) sprintf_s format string requires 5 parameters but 6 are given.\n" - "[test.cpp:6]: (warning) sprintf_s format string requires 5 parameters but 6 are given.\n", errout.str()); + 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" + "[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()); }