Fixed #5057 (Microsoft secure printf/scanf support.)
This commit is contained in:
parent
e3b7bce72b
commit
c37c6617d3
|
@ -439,9 +439,10 @@ void CheckIO::checkWrongPrintfScanfArguments()
|
||||||
if (!formatString.empty()) {
|
if (!formatString.empty()) {
|
||||||
/* 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 ( %str%") ||
|
||||||
(windows && (Token::Match(tok, "Format|AppendFormat ( %str%") &&
|
(windows && (Token::Match(tok, "printf_s|wprintf_s|scanf_s|wscanf_s ( %str%") ||
|
||||||
|
(Token::Match(tok, "Format|AppendFormat ( %str%") &&
|
||||||
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")))) {
|
||||||
|
|
||||||
formatString = tok->strAt(2);
|
formatString = tok->strAt(2);
|
||||||
if (tok->strAt(3) == ",") {
|
if (tok->strAt(3) == ",") {
|
||||||
|
@ -451,7 +452,9 @@ void CheckIO::checkWrongPrintfScanfArguments()
|
||||||
} else {
|
} else {
|
||||||
continue;
|
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%"))) {
|
} 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 ( %any%"))) {
|
||||||
const Token* formatStringTok = tok->tokAt(2)->nextArgument(); // Find second parameter (format string)
|
const Token* formatStringTok = tok->tokAt(2)->nextArgument(); // Find second parameter (format string)
|
||||||
if (Token::Match(formatStringTok, "%str% [,)]")) {
|
if (Token::Match(formatStringTok, "%str% [,)]")) {
|
||||||
argListTok = formatStringTok->nextArgument(); // Find third parameter (first argument of va_args)
|
argListTok = formatStringTok->nextArgument(); // Find third parameter (first argument of va_args)
|
||||||
|
@ -459,7 +462,9 @@ void CheckIO::checkWrongPrintfScanfArguments()
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if (Token::Match(tok, "snprintf|fnprintf (") || (Token::simpleMatch(tok, "swprintf (") && !Token::Match(tok->tokAt(2)->nextArgument(), "%str%"))) {
|
} else if (Token::Match(tok, "snprintf|fnprintf (") ||
|
||||||
|
(Token::simpleMatch(tok, "swprintf (") && !Token::Match(tok->tokAt(2)->nextArgument(), "%str%")) ||
|
||||||
|
(windows && Token::Match(tok, "sprintf_s|swprintf_s ("))) {
|
||||||
const Token* formatStringTok = tok->tokAt(2);
|
const Token* formatStringTok = tok->tokAt(2);
|
||||||
for (int i = 0; i < 2 && formatStringTok; i++) {
|
for (int i = 0; i < 2 && formatStringTok; i++) {
|
||||||
formatStringTok = formatStringTok->nextArgument(); // Find third parameter (format string)
|
formatStringTok = formatStringTok->nextArgument(); // Find third parameter (format string)
|
||||||
|
@ -470,13 +475,27 @@ void CheckIO::checkWrongPrintfScanfArguments()
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
} else if (windows && Token::Match(tok, "snprintf_s|snwprintf_s (")) {
|
||||||
|
const Token* formatStringTok = tok->tokAt(2);
|
||||||
|
for (int i = 0; i < 3 && formatStringTok; i++) {
|
||||||
|
formatStringTok = formatStringTok->nextArgument(); // Find forth parameter (format string)
|
||||||
|
}
|
||||||
|
if (Token::Match(formatStringTok, "%str% [,)]")) {
|
||||||
|
argListTok = formatStringTok->nextArgument(); // Find fourth parameter (first argument of va_args)
|
||||||
|
formatString = formatStringTok->str();
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count format string parameters..
|
// Count format string parameters..
|
||||||
bool scan = Token::Match(tok, "sscanf|fscanf|scanf|swscanf|fwscanf|wscanf");
|
bool scanf_s = windows ? Token::Match(tok, "scanf_s|wscanf_s|sscanf_s|swscanf_s") : false;
|
||||||
|
bool scan = Token::Match(tok, "sscanf|fscanf|scanf|swscanf|fwscanf|wscanf") || scanf_s;
|
||||||
unsigned int numFormat = 0;
|
unsigned int numFormat = 0;
|
||||||
|
unsigned int numSecure = 0;
|
||||||
bool percent = false;
|
bool percent = false;
|
||||||
const Token* argListTok2 = argListTok;
|
const Token* argListTok2 = argListTok;
|
||||||
std::set<unsigned int> parameterPositionsUsed;
|
std::set<unsigned int> parameterPositionsUsed;
|
||||||
|
@ -561,6 +580,21 @@ void CheckIO::checkWrongPrintfScanfArguments()
|
||||||
argInfo.typeToken->strAt(-1) == "const")) {
|
argInfo.typeToken->strAt(-1) == "const")) {
|
||||||
invalidScanfArgTypeError_s(tok, numFormat, specifier, &argInfo);
|
invalidScanfArgTypeError_s(tok, numFormat, specifier, &argInfo);
|
||||||
}
|
}
|
||||||
|
if (scanf_s) {
|
||||||
|
numSecure++;
|
||||||
|
if (argListTok) {
|
||||||
|
argListTok = argListTok->nextArgument();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
if (scanf_s) {
|
||||||
|
numSecure++;
|
||||||
|
if (argListTok) {
|
||||||
|
argListTok = argListTok->nextArgument();
|
||||||
|
}
|
||||||
|
}
|
||||||
done = true;
|
done = true;
|
||||||
break;
|
break;
|
||||||
case 'x':
|
case 'x':
|
||||||
|
@ -1134,8 +1168,8 @@ void CheckIO::checkWrongPrintfScanfArguments()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mismatching number of parameters => warning
|
// Mismatching number of parameters => warning
|
||||||
if (numFormat != numFunction)
|
if ((numFormat + numSecure) != numFunction)
|
||||||
wrongPrintfScanfArgumentsError(tok, tok->str(), numFormat, numFunction);
|
wrongPrintfScanfArgumentsError(tok, tok->originalName().empty() ? tok->str() : tok->originalName(), numFormat + numSecure, numFunction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1374,12 +1408,13 @@ void CheckIO::wrongPrintfScanfArgumentsError(const Token* tok,
|
||||||
|
|
||||||
std::ostringstream errmsg;
|
std::ostringstream errmsg;
|
||||||
errmsg << functionName
|
errmsg << functionName
|
||||||
<< " format string has "
|
<< " format string requires "
|
||||||
<< numFormat
|
<< numFormat
|
||||||
<< " parameters but "
|
<< " parameter" << (numFormat != 1 ? "s" : "") << " but "
|
||||||
<< (numFormat > numFunction ? "only " : "")
|
<< (numFormat > numFunction ? "only " : "")
|
||||||
<< numFunction
|
<< numFunction
|
||||||
<< " are given.";
|
<< (numFunction != 1 ? " are" : " is")
|
||||||
|
<< " given.";
|
||||||
|
|
||||||
reportError(tok, severity, "wrongPrintfScanfArgNum", errmsg.str());
|
reportError(tok, severity, "wrongPrintfScanfArgNum", errmsg.str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -9562,14 +9562,34 @@ void Tokenizer::simplifyMicrosoftStringFunctions()
|
||||||
tok->str("strtok");
|
tok->str("strtok");
|
||||||
} else if (Token::simpleMatch(tok, "_tprintf (")) {
|
} else if (Token::simpleMatch(tok, "_tprintf (")) {
|
||||||
tok->str("printf");
|
tok->str("printf");
|
||||||
|
tok->originalName("_tprintf");
|
||||||
} else if (Token::simpleMatch(tok, "_stprintf (")) {
|
} else if (Token::simpleMatch(tok, "_stprintf (")) {
|
||||||
tok->str("sprintf");
|
tok->str("sprintf");
|
||||||
|
tok->originalName("_stprintf");
|
||||||
} else if (Token::simpleMatch(tok, "_sntprintf (")) {
|
} else if (Token::simpleMatch(tok, "_sntprintf (")) {
|
||||||
tok->str("snprintf");
|
tok->str("snprintf");
|
||||||
|
tok->originalName("_sntprintf");
|
||||||
} else if (Token::simpleMatch(tok, "_tscanf (")) {
|
} else if (Token::simpleMatch(tok, "_tscanf (")) {
|
||||||
tok->str("scanf");
|
tok->str("scanf");
|
||||||
|
tok->originalName("_tscanf");
|
||||||
} else if (Token::simpleMatch(tok, "_stscanf (")) {
|
} else if (Token::simpleMatch(tok, "_stscanf (")) {
|
||||||
tok->str("sscanf");
|
tok->str("sscanf");
|
||||||
|
tok->originalName("_stscanf");
|
||||||
|
} else if (Token::simpleMatch(tok, "_tprintf_s (")) {
|
||||||
|
tok->str("printf_s");
|
||||||
|
tok->originalName("_tprintf_s");
|
||||||
|
} else if (Token::simpleMatch(tok, "_stprintf_s (")) {
|
||||||
|
tok->str("sprintf_s");
|
||||||
|
tok->originalName("_stprintf_s");
|
||||||
|
} else if (Token::simpleMatch(tok, "_sntprintf_s (")) {
|
||||||
|
tok->str("snprintf_s");
|
||||||
|
tok->originalName("_sntprintf_s");
|
||||||
|
} else if (Token::simpleMatch(tok, "_tscanf_s (")) {
|
||||||
|
tok->str("scanf_s");
|
||||||
|
tok->originalName("_tscanf_s");
|
||||||
|
} else if (Token::simpleMatch(tok, "_stscanf_s (")) {
|
||||||
|
tok->str("sscanf_s");
|
||||||
|
tok->originalName("_stscanf_s");
|
||||||
} else if (Token::Match(tok, "_T ( %char%|%str% )")) {
|
} else if (Token::Match(tok, "_T ( %char%|%str% )")) {
|
||||||
tok->deleteNext();
|
tok->deleteNext();
|
||||||
tok->deleteThis();
|
tok->deleteThis();
|
||||||
|
@ -9612,14 +9632,34 @@ void Tokenizer::simplifyMicrosoftStringFunctions()
|
||||||
tok->str("wcstok");
|
tok->str("wcstok");
|
||||||
} else if (Token::simpleMatch(tok, "_tprintf (")) {
|
} else if (Token::simpleMatch(tok, "_tprintf (")) {
|
||||||
tok->str("wprintf");
|
tok->str("wprintf");
|
||||||
|
tok->originalName("_tprintf");
|
||||||
} else if (Token::simpleMatch(tok, "_stprintf (")) {
|
} else if (Token::simpleMatch(tok, "_stprintf (")) {
|
||||||
tok->str("swprintf");
|
tok->str("swprintf");
|
||||||
|
tok->originalName("_stprintf");
|
||||||
} else if (Token::simpleMatch(tok, "_sntprintf (")) {
|
} else if (Token::simpleMatch(tok, "_sntprintf (")) {
|
||||||
tok->str("snwprintf");
|
tok->str("snwprintf");
|
||||||
|
tok->originalName("_sntprintf");
|
||||||
} else if (Token::simpleMatch(tok, "_tscanf (")) {
|
} else if (Token::simpleMatch(tok, "_tscanf (")) {
|
||||||
tok->str("wscanf");
|
tok->str("wscanf");
|
||||||
|
tok->originalName("_tscanf");
|
||||||
} else if (Token::simpleMatch(tok, "_stscanf (")) {
|
} else if (Token::simpleMatch(tok, "_stscanf (")) {
|
||||||
tok->str("swscanf");
|
tok->str("swscanf");
|
||||||
|
tok->originalName("_stscanf");
|
||||||
|
} else if (Token::simpleMatch(tok, "_tprintf_s (")) {
|
||||||
|
tok->str("wprintf_s");
|
||||||
|
tok->originalName("_tprintf_s");
|
||||||
|
} else if (Token::simpleMatch(tok, "_stprintf_s (")) {
|
||||||
|
tok->str("swprintf_s");
|
||||||
|
tok->originalName("_stprintf_s");
|
||||||
|
} else if (Token::simpleMatch(tok, "_sntprintf_s (")) {
|
||||||
|
tok->str("snwprintf_s");
|
||||||
|
tok->originalName("_sntprintf_s");
|
||||||
|
} else if (Token::simpleMatch(tok, "_tscanf_s (")) {
|
||||||
|
tok->str("wscanf_s");
|
||||||
|
tok->originalName("_tscanf_s");
|
||||||
|
} else if (Token::simpleMatch(tok, "_stscanf_s (")) {
|
||||||
|
tok->str("swscanf_s");
|
||||||
|
tok->originalName("_stscanf_s");
|
||||||
} else if (Token::Match(tok, "_T ( %char%|%str% )")) {
|
} else if (Token::Match(tok, "_T ( %char%|%str% )")) {
|
||||||
tok->deleteNext();
|
tok->deleteNext();
|
||||||
tok->deleteThis();
|
tok->deleteThis();
|
||||||
|
|
156
test/testio.cpp
156
test/testio.cpp
|
@ -50,6 +50,8 @@ private:
|
||||||
|
|
||||||
TEST_CASE(testMicrosoftPrintfArgument); // ticket #4902
|
TEST_CASE(testMicrosoftPrintfArgument); // ticket #4902
|
||||||
TEST_CASE(testMicrosoftCStringFormatArguments); // ticket #4920
|
TEST_CASE(testMicrosoftCStringFormatArguments); // ticket #4920
|
||||||
|
TEST_CASE(testMicrosoftSecurePrintfArgument);
|
||||||
|
TEST_CASE(testMicrosoftSecureScanfArgument);
|
||||||
|
|
||||||
TEST_CASE(testlibrarycfg); // library configuration
|
TEST_CASE(testlibrarycfg); // library configuration
|
||||||
}
|
}
|
||||||
|
@ -460,7 +462,7 @@ private:
|
||||||
" scanf(\"aa%ld\", &a);\n" // No %s
|
" scanf(\"aa%ld\", &a);\n" // No %s
|
||||||
" scanf(\"%*[^~]\");\n" // Ignore input
|
" scanf(\"%*[^~]\");\n" // Ignore input
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:4]: (warning) scanf format string has 0 parameters but 1 are given.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:4]: (warning) scanf format string requires 0 parameters but 1 is given.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void testScanf3() {
|
void testScanf3() {
|
||||||
|
@ -507,10 +509,10 @@ private:
|
||||||
" fscanf(bar, \"%1d\", &foo, &bar);\n"
|
" fscanf(bar, \"%1d\", &foo, &bar);\n"
|
||||||
" scanf(\"%*1x %1x %29s\", &count, KeyName, foo);\n"
|
" scanf(\"%*1x %1x %29s\", &count, KeyName, foo);\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning) scanf format string has 0 parameters but 1 are given.\n"
|
ASSERT_EQUALS("[test.cpp:2]: (warning) scanf format string requires 0 parameters but 1 is given.\n"
|
||||||
"[test.cpp:3]: (warning) scanf format string has 1 parameters but 2 are given.\n"
|
"[test.cpp:3]: (warning) scanf format string requires 1 parameter but 2 are given.\n"
|
||||||
"[test.cpp:4]: (warning) fscanf format string has 1 parameters but 2 are given.\n"
|
"[test.cpp:4]: (warning) fscanf format string requires 1 parameter but 2 are given.\n"
|
||||||
"[test.cpp:5]: (warning) scanf format string has 2 parameters but 3 are given.\n", errout.str());
|
"[test.cpp:5]: (warning) scanf format string requires 2 parameters but 3 are given.\n", errout.str());
|
||||||
|
|
||||||
check("void foo() {\n"
|
check("void foo() {\n"
|
||||||
" scanf(\"%1d\");\n"
|
" scanf(\"%1d\");\n"
|
||||||
|
@ -518,10 +520,10 @@ private:
|
||||||
" sscanf(bar, \"%1d%1d\", &foo);\n"
|
" sscanf(bar, \"%1d%1d\", &foo);\n"
|
||||||
" scanf(\"%*1x %1x %29s\", &count);\n"
|
" scanf(\"%*1x %1x %29s\", &count);\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (error) scanf format string has 1 parameters but only 0 are given.\n"
|
ASSERT_EQUALS("[test.cpp:2]: (error) scanf format string requires 1 parameter but only 0 are given.\n"
|
||||||
"[test.cpp:3]: (error) scanf format string has 2 parameters but only 1 are given.\n"
|
"[test.cpp:3]: (error) scanf format string requires 2 parameters but only 1 is given.\n"
|
||||||
"[test.cpp:4]: (error) sscanf format string has 2 parameters but only 1 are given.\n"
|
"[test.cpp:4]: (error) sscanf format string requires 2 parameters but only 1 is given.\n"
|
||||||
"[test.cpp:5]: (error) scanf format string has 2 parameters but only 1 are given.\n", errout.str());
|
"[test.cpp:5]: (error) scanf format string requires 2 parameters but only 1 is given.\n", errout.str());
|
||||||
|
|
||||||
check("void foo() {\n"
|
check("void foo() {\n"
|
||||||
" char input[10];\n"
|
" char input[10];\n"
|
||||||
|
@ -1316,24 +1318,24 @@ private:
|
||||||
" sprintf(string1, \"%-*.*s\", 32, string2);\n" // #3364
|
" sprintf(string1, \"%-*.*s\", 32, string2);\n" // #3364
|
||||||
" snprintf(a, 9, \"%s%d\", \"11223344\");\n" // #3655
|
" snprintf(a, 9, \"%s%d\", \"11223344\");\n" // #3655
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (error) printf format string has 1 parameters but only 0 are given.\n"
|
ASSERT_EQUALS("[test.cpp:2]: (error) printf format string requires 1 parameter but only 0 are given.\n"
|
||||||
"[test.cpp:3]: (error) printf format string has 2 parameters but only 1 are given.\n"
|
"[test.cpp:3]: (error) printf format string requires 2 parameters but only 1 is given.\n"
|
||||||
"[test.cpp:4]: (error) printf format string has 3 parameters but only 2 are given.\n"
|
"[test.cpp:4]: (error) printf format string requires 3 parameters but only 2 are given.\n"
|
||||||
"[test.cpp:5]: (error) printf format string has 3 parameters but only 2 are given.\n"
|
"[test.cpp:5]: (error) printf format string requires 3 parameters but only 2 are given.\n"
|
||||||
"[test.cpp:6]: (error) printf format string has 3 parameters but only 2 are given.\n"
|
"[test.cpp:6]: (error) printf format string requires 3 parameters but only 2 are given.\n"
|
||||||
"[test.cpp:7]: (error) fprintf format string has 2 parameters but only 0 are given.\n"
|
"[test.cpp:7]: (error) fprintf format string requires 2 parameters but only 0 are given.\n"
|
||||||
"[test.cpp:8]: (error) snprintf format string has 2 parameters but only 0 are given.\n"
|
"[test.cpp:8]: (error) snprintf format string requires 2 parameters but only 0 are given.\n"
|
||||||
"[test.cpp:9]: (error) sprintf format string has 3 parameters but only 2 are given.\n"
|
"[test.cpp:9]: (error) sprintf format string requires 3 parameters but only 2 are given.\n"
|
||||||
"[test.cpp:10]: (error) snprintf format string has 2 parameters but only 1 are given.\n", errout.str());
|
"[test.cpp:10]: (error) snprintf format string requires 2 parameters but only 1 is given.\n", errout.str());
|
||||||
|
|
||||||
check("void foo(char *str) {\n"
|
check("void foo(char *str) {\n"
|
||||||
" printf(\"\", 0);\n"
|
" printf(\"\", 0);\n"
|
||||||
" printf(\"%u\", 123, bar());\n"
|
" printf(\"%u\", 123, bar());\n"
|
||||||
" printf(\"%u%s\", 0, bar(), 43123);\n"
|
" printf(\"%u%s\", 0, bar(), 43123);\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning) printf format string has 0 parameters but 1 are given.\n"
|
ASSERT_EQUALS("[test.cpp:2]: (warning) printf format string requires 0 parameters but 1 is given.\n"
|
||||||
"[test.cpp:3]: (warning) printf format string has 1 parameters but 2 are given.\n"
|
"[test.cpp:3]: (warning) printf format string requires 1 parameter but 2 are given.\n"
|
||||||
"[test.cpp:4]: (warning) printf format string has 2 parameters but 3 are given.\n", errout.str());
|
"[test.cpp:4]: (warning) printf format string requires 2 parameters but 3 are given.\n", errout.str());
|
||||||
|
|
||||||
check("void foo() {\n" // swprintf exists as MSVC extension and as standard function: #4790
|
check("void foo() {\n" // swprintf exists as MSVC extension and as standard function: #4790
|
||||||
" swprintf(string1, L\"%u\", 32, string2);\n" // MSVC implementation
|
" swprintf(string1, L\"%u\", 32, string2);\n" // MSVC implementation
|
||||||
|
@ -1341,8 +1343,8 @@ private:
|
||||||
" swprintf(string1, 6, L\"%u\", 32, string2);\n" // Standard implementation
|
" swprintf(string1, 6, L\"%u\", 32, string2);\n" // Standard implementation
|
||||||
" swprintf(string1, 6, L\"%u%s\", 32, string2);\n" // Standard implementation
|
" swprintf(string1, 6, L\"%u%s\", 32, string2);\n" // Standard implementation
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning) swprintf format string has 1 parameters but 2 are given.\n"
|
ASSERT_EQUALS("[test.cpp:2]: (warning) swprintf format string requires 1 parameter but 2 are given.\n"
|
||||||
"[test.cpp:4]: (warning) swprintf format string has 1 parameters but 2 are given.\n", errout.str());
|
"[test.cpp:4]: (warning) swprintf format string requires 1 parameter but 2 are given.\n", errout.str());
|
||||||
|
|
||||||
check("void foo(char *str) {\n"
|
check("void foo(char *str) {\n"
|
||||||
" printf(\"%u\", 0);\n"
|
" printf(\"%u\", 0);\n"
|
||||||
|
@ -2052,7 +2054,7 @@ private:
|
||||||
" scanf(\"%2$d\", &bar);\n"
|
" scanf(\"%2$d\", &bar);\n"
|
||||||
" printf(\"%0$f\", 0.0);\n"
|
" printf(\"%0$f\", 0.0);\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (error) printf format string has 1 parameters but only 0 are given.\n"
|
ASSERT_EQUALS("[test.cpp:3]: (error) printf format string requires 1 parameter but only 0 are given.\n"
|
||||||
"[test.cpp:4]: (warning) printf: referencing parameter 4 while 3 arguments given\n"
|
"[test.cpp:4]: (warning) printf: referencing parameter 4 while 3 arguments given\n"
|
||||||
"[test.cpp:5]: (warning) scanf: referencing parameter 2 while 1 arguments given\n"
|
"[test.cpp:5]: (warning) scanf: referencing parameter 2 while 1 arguments given\n"
|
||||||
"[test.cpp:6]: (warning) printf: parameter positions start at 1, not 0\n"
|
"[test.cpp:6]: (warning) printf: parameter positions start at 1, not 0\n"
|
||||||
|
@ -2164,6 +2166,110 @@ private:
|
||||||
"[test.cpp:5]: (warning) %I32d in format string (no. 1) requires '__int32' but the argument type is 'unsigned __int32 {aka unsigned int}'.\n", errout.str());
|
"[test.cpp:5]: (warning) %I32d in format string (no. 1) requires '__int32' but the argument type is 'unsigned __int32 {aka unsigned int}'.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testMicrosoftSecurePrintfArgument() {
|
||||||
|
check("void foo() {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" unsigned int u;\n"
|
||||||
|
" _tprintf_s(_T(\"%d %u\"), u, i, 0);\n"
|
||||||
|
"}\n", false, false, Settings::Win32A);
|
||||||
|
ASSERT_EQUALS("[test.cpp:4]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'.\n"
|
||||||
|
"[test.cpp:4]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'int'.\n"
|
||||||
|
"[test.cpp:4]: (warning) _tprintf_s format string requires 2 parameters but 3 are given.\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo() {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" unsigned int u;\n"
|
||||||
|
" _tprintf_s(_T(\"%d %u\"), u, i, 0);\n"
|
||||||
|
"}\n", false, false, Settings::Win32W);
|
||||||
|
ASSERT_EQUALS("[test.cpp:4]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'.\n"
|
||||||
|
"[test.cpp:4]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'int'.\n"
|
||||||
|
"[test.cpp:4]: (warning) _tprintf_s format string requires 2 parameters but 3 are given.\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo() {\n"
|
||||||
|
" TCHAR str[10];\n"
|
||||||
|
" int i;\n"
|
||||||
|
" unsigned int u;\n"
|
||||||
|
" _stprintf_s(str, sizeof(str) / sizeof(TCHAR), _T(\"%d %u\"), u, i, 0);\n"
|
||||||
|
"}\n", false, false, Settings::Win32A);
|
||||||
|
ASSERT_EQUALS("[test.cpp:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'.\n"
|
||||||
|
"[test.cpp:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'int'.\n"
|
||||||
|
"[test.cpp:5]: (warning) _stprintf_s format string requires 2 parameters but 3 are given.\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo() {\n"
|
||||||
|
" TCHAR str[10];\n"
|
||||||
|
" int i;\n"
|
||||||
|
" unsigned int u;\n"
|
||||||
|
" _stprintf_s(str, sizeof(str) / sizeof(TCHAR), _T(\"%d %u\"), u, i, 0);\n"
|
||||||
|
"}\n", false, false, Settings::Win32W);
|
||||||
|
ASSERT_EQUALS("[test.cpp:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'.\n"
|
||||||
|
"[test.cpp:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'int'.\n"
|
||||||
|
"[test.cpp:5]: (warning) _stprintf_s format string requires 2 parameters but 3 are given.\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo() {\n"
|
||||||
|
" TCHAR str[10];\n"
|
||||||
|
" int i;\n"
|
||||||
|
" unsigned int u;\n"
|
||||||
|
" _sntprintf_s(str, sizeof(str) / sizeof(TCHAR), _TRUNCATE, _T(\"%d %u\"), u, i, 0);\n"
|
||||||
|
"}\n", false, false, Settings::Win32A);
|
||||||
|
ASSERT_EQUALS("[test.cpp:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'.\n"
|
||||||
|
"[test.cpp:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'int'.\n"
|
||||||
|
"[test.cpp:5]: (warning) _sntprintf_s format string requires 2 parameters but 3 are given.\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo() {\n"
|
||||||
|
" TCHAR str[10];\n"
|
||||||
|
" int i;\n"
|
||||||
|
" unsigned int u;\n"
|
||||||
|
" _sntprintf_s(str, sizeof(str) / sizeof(TCHAR), _TRUNCATE, _T(\"%d %u\"), u, i, 0);\n"
|
||||||
|
"}\n", false, false, Settings::Win32W);
|
||||||
|
ASSERT_EQUALS("[test.cpp:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'.\n"
|
||||||
|
"[test.cpp:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'int'.\n"
|
||||||
|
"[test.cpp:5]: (warning) _sntprintf_s format string requires 2 parameters but 3 are given.\n", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void testMicrosoftSecureScanfArgument() {
|
||||||
|
check("void foo() {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" unsigned int u;\n"
|
||||||
|
" TCHAR str[10];\n"
|
||||||
|
" _tscanf_s(\"%s %d %u\", str, 10, &u, &i, 0)\n"
|
||||||
|
"}\n", false, false, Settings::Win32A);
|
||||||
|
ASSERT_EQUALS("[test.cpp:5]: (warning) %d in format string (no. 2) requires 'int *' but the argument type is 'unsigned int *'.\n"
|
||||||
|
"[test.cpp:5]: (warning) %u in format string (no. 3) requires 'unsigned int *' but the argument type is 'int *'.\n"
|
||||||
|
"[test.cpp:5]: (warning) _tscanf_s format string requires 4 parameters but 5 are given.\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo() {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" unsigned int u;\n"
|
||||||
|
" TCHAR str[10];\n"
|
||||||
|
" _tscanf_s(\"%s %d %u\", str, 10, &u, &i, 0)\n"
|
||||||
|
"}\n", false, false, Settings::Win32W);
|
||||||
|
ASSERT_EQUALS("[test.cpp:5]: (warning) %d in format string (no. 2) requires 'int *' but the argument type is 'unsigned int *'.\n"
|
||||||
|
"[test.cpp:5]: (warning) %u in format string (no. 3) requires 'unsigned int *' but the argument type is 'int *'.\n"
|
||||||
|
"[test.cpp:5]: (warning) _tscanf_s format string requires 4 parameters but 5 are given.\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo() {\n"
|
||||||
|
" TCHAR txt[100];\n"
|
||||||
|
" int i;\n"
|
||||||
|
" unsigned int u;\n"
|
||||||
|
" TCHAR str[10];\n"
|
||||||
|
" _stscanf_s(txt, \"%s %d %u\", str, 10, &u, &i, 0)\n"
|
||||||
|
"}\n", false, false, Settings::Win32A);
|
||||||
|
ASSERT_EQUALS("[test.cpp:6]: (warning) %d in format string (no. 2) requires 'int *' but the argument type is 'unsigned int *'.\n"
|
||||||
|
"[test.cpp:6]: (warning) %u in format string (no. 3) requires 'unsigned int *' but the argument type is 'int *'.\n"
|
||||||
|
"[test.cpp:6]: (warning) _stscanf_s format string requires 4 parameters but 5 are given.\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo() {\n"
|
||||||
|
" TCHAR txt[100];\n"
|
||||||
|
" int i;\n"
|
||||||
|
" unsigned int u;\n"
|
||||||
|
" TCHAR str[10];\n"
|
||||||
|
" _stscanf_s(txt, \"%s %d %u\", str, 10, &u, &i, 0)\n"
|
||||||
|
"}\n", false, false, Settings::Win32W);
|
||||||
|
ASSERT_EQUALS("[test.cpp:6]: (warning) %d in format string (no. 2) requires 'int *' but the argument type is 'unsigned int *'.\n"
|
||||||
|
"[test.cpp:6]: (warning) %u in format string (no. 3) requires 'unsigned int *' but the argument type is 'int *'.\n"
|
||||||
|
"[test.cpp:6]: (warning) _stscanf_s format string requires 4 parameters but 5 are given.\n", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void testlibrarycfg() {
|
void testlibrarycfg() {
|
||||||
const char code[] = "void f() {\n"
|
const char code[] = "void f() {\n"
|
||||||
" format(\"%s\");\n"
|
" format(\"%s\");\n"
|
||||||
|
@ -2177,7 +2283,7 @@ private:
|
||||||
Library lib;
|
Library lib;
|
||||||
lib.argumentChecks["format"][1].formatstr = true;
|
lib.argumentChecks["format"][1].formatstr = true;
|
||||||
check(code, false, false, Settings::Unspecified, &lib);
|
check(code, false, false, Settings::Unspecified, &lib);
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (error) format format string has 1 parameters but only 0 are given.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2]: (error) format format string requires 1 parameter but only 0 are given.\n", errout.str());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue