CheckIO: This patch adds support for fprintf_s, fscanf_s and %I. Ticket: #5051
This commit is contained in:
parent
022e7a0f0f
commit
59de30823e
|
@ -454,7 +454,7 @@ void CheckIO::checkWrongPrintfScanfArguments()
|
||||||
}
|
}
|
||||||
} 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 ( %any%"))) {
|
(windows && Token::Match(tok, "sscanf_s|swscanf_s|fscanf_s|fwscanf_s|fprintf_s|fwprintf_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)
|
||||||
|
@ -492,7 +492,7 @@ void CheckIO::checkWrongPrintfScanfArguments()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count format string parameters..
|
// Count format string parameters..
|
||||||
bool scanf_s = windows ? Token::Match(tok, "scanf_s|wscanf_s|sscanf_s|swscanf_s") : false;
|
bool scanf_s = windows ? Token::Match(tok, "scanf_s|wscanf_s|sscanf_s|swscanf_s|fscanf_s|fwscanf_s") : false;
|
||||||
bool scan = Token::Match(tok, "sscanf|fscanf|scanf|swscanf|fwscanf|wscanf") || scanf_s;
|
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;
|
unsigned int numSecure = 0;
|
||||||
|
@ -661,7 +661,14 @@ void CheckIO::checkWrongPrintfScanfArguments()
|
||||||
invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true);
|
invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true);
|
||||||
break;
|
break;
|
||||||
case 'I':
|
case 'I':
|
||||||
if (argInfo.typeToken->str() != "long" || !argInfo.typeToken->isLong())
|
if (specifier.find("I64") != std::string::npos) {
|
||||||
|
if (argInfo.typeToken->str() != "long" || !argInfo.typeToken->isLong())
|
||||||
|
invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true);
|
||||||
|
} else if (specifier.find("I32") != std::string::npos) {
|
||||||
|
if (argInfo.typeToken->str() != "int" || argInfo.typeToken->isLong())
|
||||||
|
invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true);
|
||||||
|
} else if (argInfo.typeToken->originalName() != "ptrdiff_t" &&
|
||||||
|
argInfo.typeToken->originalName() != "size_t")
|
||||||
invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true);
|
invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true);
|
||||||
break;
|
break;
|
||||||
case 'j':
|
case 'j':
|
||||||
|
@ -726,7 +733,13 @@ void CheckIO::checkWrongPrintfScanfArguments()
|
||||||
invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, false);
|
invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, false);
|
||||||
break;
|
break;
|
||||||
case 'I':
|
case 'I':
|
||||||
if (argInfo.typeToken->str() != "long" || !argInfo.typeToken->isLong())
|
if (specifier.find("I64") != std::string::npos) {
|
||||||
|
if (argInfo.typeToken->str() != "long" || !argInfo.typeToken->isLong())
|
||||||
|
invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, false);
|
||||||
|
} else if (specifier.find("I32") != std::string::npos) {
|
||||||
|
if (argInfo.typeToken->str() != "int" || argInfo.typeToken->isLong())
|
||||||
|
invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, false);
|
||||||
|
} else if (argInfo.typeToken->originalName() != "ptrdiff_t")
|
||||||
invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, false);
|
invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, false);
|
||||||
break;
|
break;
|
||||||
case 'j':
|
case 'j':
|
||||||
|
@ -787,7 +800,13 @@ void CheckIO::checkWrongPrintfScanfArguments()
|
||||||
invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true);
|
invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true);
|
||||||
break;
|
break;
|
||||||
case 'I':
|
case 'I':
|
||||||
if (argInfo.typeToken->str() != "long" || !argInfo.typeToken->isLong())
|
if (specifier.find("I64") != std::string::npos) {
|
||||||
|
if (argInfo.typeToken->str() != "long" || !argInfo.typeToken->isLong())
|
||||||
|
invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true);
|
||||||
|
} else if (specifier.find("I32") != std::string::npos) {
|
||||||
|
if (argInfo.typeToken->str() != "int" || argInfo.typeToken->isLong())
|
||||||
|
invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true);
|
||||||
|
} else if (argInfo.typeToken->originalName() != "size_t")
|
||||||
invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true);
|
invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true);
|
||||||
break;
|
break;
|
||||||
case 'j':
|
case 'j':
|
||||||
|
@ -853,8 +872,10 @@ void CheckIO::checkWrongPrintfScanfArguments()
|
||||||
done = true;
|
done = true;
|
||||||
break;
|
break;
|
||||||
case 'I':
|
case 'I':
|
||||||
if (i+1 != formatString.end() && *(i+1) == '6' &&
|
if ((i+1 != formatString.end() && *(i+1) == '6' &&
|
||||||
i+2 != formatString.end() && *(i+2) == '4') {
|
i+2 != formatString.end() && *(i+2) == '4') ||
|
||||||
|
(i+1 != formatString.end() && *(i+1) == '3' &&
|
||||||
|
i+2 != formatString.end() && *(i+2) == '2')) {
|
||||||
specifier += *i++;
|
specifier += *i++;
|
||||||
specifier += *i++;
|
specifier += *i++;
|
||||||
if ((i+1) != formatString.end() && !isalpha(*(i+1))) {
|
if ((i+1) != formatString.end() && !isalpha(*(i+1))) {
|
||||||
|
@ -865,9 +886,13 @@ void CheckIO::checkWrongPrintfScanfArguments()
|
||||||
specifier += *i++;
|
specifier += *i++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
specifier += *i;
|
if ((i+1) != formatString.end() && !isalpha(*(i+1))) {
|
||||||
invalidLengthModifierError(tok, numFormat, specifier);
|
specifier += *i;
|
||||||
done = true;
|
invalidLengthModifierError(tok, numFormat, specifier);
|
||||||
|
done = true;
|
||||||
|
} else {
|
||||||
|
specifier += *i++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
|
@ -1497,8 +1522,12 @@ void CheckIO::invalidScanfArgTypeError_int(const Token* tok, unsigned int numFor
|
||||||
errmsg << (isUnsigned ? "unsigned " : "") << "long long";
|
errmsg << (isUnsigned ? "unsigned " : "") << "long long";
|
||||||
else
|
else
|
||||||
errmsg << (isUnsigned ? "unsigned " : "") << "long";
|
errmsg << (isUnsigned ? "unsigned " : "") << "long";
|
||||||
} else if (specifier[0] == 'I') {
|
} else if (specifier.find("I32") != std::string::npos) {
|
||||||
|
errmsg << (isUnsigned ? "unsigned " : "") << "__int32";
|
||||||
|
} else if (specifier.find("I64") != std::string::npos) {
|
||||||
errmsg << (isUnsigned ? "unsigned " : "") << "__int64";
|
errmsg << (isUnsigned ? "unsigned " : "") << "__int64";
|
||||||
|
} else if (specifier[0] == 'I') {
|
||||||
|
errmsg << (isUnsigned ? "size_t" : "ptrdiff_t");
|
||||||
} else if (specifier[0] == 'j') {
|
} else if (specifier[0] == 'j') {
|
||||||
if (isUnsigned)
|
if (isUnsigned)
|
||||||
errmsg << "uintmax_t";
|
errmsg << "uintmax_t";
|
||||||
|
|
|
@ -9604,6 +9604,9 @@ void Tokenizer::simplifyMicrosoftStringFunctions()
|
||||||
tok->str("strstr");
|
tok->str("strstr");
|
||||||
} else if (Token::simpleMatch(tok, "_tcstok (")) {
|
} else if (Token::simpleMatch(tok, "_tcstok (")) {
|
||||||
tok->str("strtok");
|
tok->str("strtok");
|
||||||
|
} else if (Token::simpleMatch(tok, "_ftprintf (")) {
|
||||||
|
tok->str("fprintf");
|
||||||
|
tok->originalName("_ftprintf");
|
||||||
} else if (Token::simpleMatch(tok, "_tprintf (")) {
|
} else if (Token::simpleMatch(tok, "_tprintf (")) {
|
||||||
tok->str("printf");
|
tok->str("printf");
|
||||||
tok->originalName("_tprintf");
|
tok->originalName("_tprintf");
|
||||||
|
@ -9613,12 +9616,18 @@ void Tokenizer::simplifyMicrosoftStringFunctions()
|
||||||
} else if (Token::simpleMatch(tok, "_sntprintf (")) {
|
} else if (Token::simpleMatch(tok, "_sntprintf (")) {
|
||||||
tok->str("snprintf");
|
tok->str("snprintf");
|
||||||
tok->originalName("_sntprintf");
|
tok->originalName("_sntprintf");
|
||||||
|
} else if (Token::simpleMatch(tok, "_ftscanf (")) {
|
||||||
|
tok->str("fscanf");
|
||||||
|
tok->originalName("_ftscanf");
|
||||||
} else if (Token::simpleMatch(tok, "_tscanf (")) {
|
} else if (Token::simpleMatch(tok, "_tscanf (")) {
|
||||||
tok->str("scanf");
|
tok->str("scanf");
|
||||||
tok->originalName("_tscanf");
|
tok->originalName("_tscanf");
|
||||||
} else if (Token::simpleMatch(tok, "_stscanf (")) {
|
} else if (Token::simpleMatch(tok, "_stscanf (")) {
|
||||||
tok->str("sscanf");
|
tok->str("sscanf");
|
||||||
tok->originalName("_stscanf");
|
tok->originalName("_stscanf");
|
||||||
|
} else if (Token::simpleMatch(tok, "_ftprintf_s (")) {
|
||||||
|
tok->str("fprintf_s");
|
||||||
|
tok->originalName("_ftprintf_s");
|
||||||
} else if (Token::simpleMatch(tok, "_tprintf_s (")) {
|
} else if (Token::simpleMatch(tok, "_tprintf_s (")) {
|
||||||
tok->str("printf_s");
|
tok->str("printf_s");
|
||||||
tok->originalName("_tprintf_s");
|
tok->originalName("_tprintf_s");
|
||||||
|
@ -9628,6 +9637,9 @@ void Tokenizer::simplifyMicrosoftStringFunctions()
|
||||||
} else if (Token::simpleMatch(tok, "_sntprintf_s (")) {
|
} else if (Token::simpleMatch(tok, "_sntprintf_s (")) {
|
||||||
tok->str("_snprintf_s");
|
tok->str("_snprintf_s");
|
||||||
tok->originalName("_sntprintf_s");
|
tok->originalName("_sntprintf_s");
|
||||||
|
} else if (Token::simpleMatch(tok, "_ftscanf_s (")) {
|
||||||
|
tok->str("fscanf_s");
|
||||||
|
tok->originalName("_ftscanf_s");
|
||||||
} else if (Token::simpleMatch(tok, "_tscanf_s (")) {
|
} else if (Token::simpleMatch(tok, "_tscanf_s (")) {
|
||||||
tok->str("scanf_s");
|
tok->str("scanf_s");
|
||||||
tok->originalName("_tscanf_s");
|
tok->originalName("_tscanf_s");
|
||||||
|
@ -9674,6 +9686,9 @@ void Tokenizer::simplifyMicrosoftStringFunctions()
|
||||||
tok->str("wcsstr");
|
tok->str("wcsstr");
|
||||||
} else if (Token::simpleMatch(tok, "_tcstok (")) {
|
} else if (Token::simpleMatch(tok, "_tcstok (")) {
|
||||||
tok->str("wcstok");
|
tok->str("wcstok");
|
||||||
|
} else if (Token::simpleMatch(tok, "_ftprintf (")) {
|
||||||
|
tok->str("fwprintf");
|
||||||
|
tok->originalName("_ftprintf");
|
||||||
} else if (Token::simpleMatch(tok, "_tprintf (")) {
|
} else if (Token::simpleMatch(tok, "_tprintf (")) {
|
||||||
tok->str("wprintf");
|
tok->str("wprintf");
|
||||||
tok->originalName("_tprintf");
|
tok->originalName("_tprintf");
|
||||||
|
@ -9683,12 +9698,18 @@ void Tokenizer::simplifyMicrosoftStringFunctions()
|
||||||
} else if (Token::simpleMatch(tok, "_sntprintf (")) {
|
} else if (Token::simpleMatch(tok, "_sntprintf (")) {
|
||||||
tok->str("snwprintf");
|
tok->str("snwprintf");
|
||||||
tok->originalName("_sntprintf");
|
tok->originalName("_sntprintf");
|
||||||
|
} else if (Token::simpleMatch(tok, "_ftscanf (")) {
|
||||||
|
tok->str("fwscanf");
|
||||||
|
tok->originalName("_ftscanf");
|
||||||
} else if (Token::simpleMatch(tok, "_tscanf (")) {
|
} else if (Token::simpleMatch(tok, "_tscanf (")) {
|
||||||
tok->str("wscanf");
|
tok->str("wscanf");
|
||||||
tok->originalName("_tscanf");
|
tok->originalName("_tscanf");
|
||||||
} else if (Token::simpleMatch(tok, "_stscanf (")) {
|
} else if (Token::simpleMatch(tok, "_stscanf (")) {
|
||||||
tok->str("swscanf");
|
tok->str("swscanf");
|
||||||
tok->originalName("_stscanf");
|
tok->originalName("_stscanf");
|
||||||
|
} else if (Token::simpleMatch(tok, "_ftprintf_s (")) {
|
||||||
|
tok->str("fwprintf_s");
|
||||||
|
tok->originalName("_ftprintf_s");
|
||||||
} else if (Token::simpleMatch(tok, "_tprintf_s (")) {
|
} else if (Token::simpleMatch(tok, "_tprintf_s (")) {
|
||||||
tok->str("wprintf_s");
|
tok->str("wprintf_s");
|
||||||
tok->originalName("_tprintf_s");
|
tok->originalName("_tprintf_s");
|
||||||
|
@ -9698,6 +9719,9 @@ void Tokenizer::simplifyMicrosoftStringFunctions()
|
||||||
} else if (Token::simpleMatch(tok, "_sntprintf_s (")) {
|
} else if (Token::simpleMatch(tok, "_sntprintf_s (")) {
|
||||||
tok->str("_snwprintf_s");
|
tok->str("_snwprintf_s");
|
||||||
tok->originalName("_sntprintf_s");
|
tok->originalName("_sntprintf_s");
|
||||||
|
} else if (Token::simpleMatch(tok, "_ftscanf_s (")) {
|
||||||
|
tok->str("fwscanf_s");
|
||||||
|
tok->originalName("_ftscanf_s");
|
||||||
} else if (Token::simpleMatch(tok, "_tscanf_s (")) {
|
} else if (Token::simpleMatch(tok, "_tscanf_s (")) {
|
||||||
tok->str("wscanf_s");
|
tok->str("wscanf_s");
|
||||||
tok->originalName("_tscanf_s");
|
tok->originalName("_tscanf_s");
|
||||||
|
|
154
test/testio.cpp
154
test/testio.cpp
|
@ -49,6 +49,7 @@ private:
|
||||||
TEST_CASE(testPosixPrintfScanfParameterPosition); // #4900
|
TEST_CASE(testPosixPrintfScanfParameterPosition); // #4900
|
||||||
|
|
||||||
TEST_CASE(testMicrosoftPrintfArgument); // ticket #4902
|
TEST_CASE(testMicrosoftPrintfArgument); // ticket #4902
|
||||||
|
TEST_CASE(testMicrosoftScanfArgument);
|
||||||
TEST_CASE(testMicrosoftCStringFormatArguments); // ticket #4920
|
TEST_CASE(testMicrosoftCStringFormatArguments); // ticket #4920
|
||||||
TEST_CASE(testMicrosoftSecurePrintfArgument);
|
TEST_CASE(testMicrosoftSecurePrintfArgument);
|
||||||
TEST_CASE(testMicrosoftSecureScanfArgument);
|
TEST_CASE(testMicrosoftSecureScanfArgument);
|
||||||
|
@ -2146,6 +2147,83 @@ 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());
|
"[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 testMicrosoftScanfArgument() {
|
||||||
|
check("void foo() {\n"
|
||||||
|
" size_t s;\n"
|
||||||
|
" ptrdiff_t p;\n"
|
||||||
|
" __int32 i32;\n"
|
||||||
|
" unsigned __int32 u32;\n"
|
||||||
|
" __int64 i64;\n"
|
||||||
|
" unsigned __int64 u64;\n"
|
||||||
|
" scanf(\"%Id %Iu %Ix\", &s, &s, &s);\n"
|
||||||
|
" scanf(\"%Id %Iu %Ix\", &p, &p, &p);\n"
|
||||||
|
" scanf(\"%I32d %I32u %I32x\", &i32, &i32, &i32);\n"
|
||||||
|
" scanf(\"%I32d %I32u %I32x\", &u32, &u32, &u32);\n"
|
||||||
|
" scanf(\"%I64d %I64u %I64x\", &i64, &i64, &i64);\n"
|
||||||
|
" scanf(\"%I64d %I64u %I64x\", &u64, &u64, &u64);\n"
|
||||||
|
"}", false, false, Settings::Win32A);
|
||||||
|
ASSERT_EQUALS("[test.cpp:8]: (warning) %Id in format string (no. 1) requires 'ptrdiff_t *' but the argument type is 'size_t * {aka unsigned long *}'.\n"
|
||||||
|
"[test.cpp:9]: (warning) %Iu in format string (no. 2) requires 'size_t *' but the argument type is 'ptrdiff_t * {aka long *}'.\n"
|
||||||
|
"[test.cpp:10]: (warning) %I32u in format string (no. 2) requires 'unsigned __int32 *' but the argument type is '__int32 * {aka int *}'.\n"
|
||||||
|
"[test.cpp:11]: (warning) %I32d in format string (no. 1) requires '__int32 *' but the argument type is 'unsigned __int32 * {aka unsigned int *}'.\n"
|
||||||
|
"[test.cpp:12]: (warning) %I64u in format string (no. 2) requires 'unsigned __int64 *' but the argument type is '__int64 * {aka long long *}'.\n"
|
||||||
|
"[test.cpp:13]: (warning) %I64d in format string (no. 1) requires '__int64 *' but the argument type is 'unsigned __int64 * {aka unsigned long long *}'.\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo() {\n"
|
||||||
|
" size_t s;\n"
|
||||||
|
" ptrdiff_t p;\n"
|
||||||
|
" __int32 i32;\n"
|
||||||
|
" unsigned __int32 u32;\n"
|
||||||
|
" __int64 i64;\n"
|
||||||
|
" unsigned __int64 u64;\n"
|
||||||
|
" scanf(\"%Id %Iu %Ix\", &s, &s, &s);\n"
|
||||||
|
" scanf(\"%Id %Iu %Ix\", &p, &p, &p);\n"
|
||||||
|
" scanf(\"%I32d %I32u %I32x\", &i32, &i32, &i32);\n"
|
||||||
|
" scanf(\"%I32d %I32u %I32x\", &u32, &u32, &u32);\n"
|
||||||
|
" scanf(\"%I64d %I64u %I64x\", &i64, &i64, &i64);\n"
|
||||||
|
" scanf(\"%I64d %I64u %I64x\", &u64, &u64, &u64);\n"
|
||||||
|
"}", false, false, Settings::Win64);
|
||||||
|
ASSERT_EQUALS("[test.cpp:8]: (warning) %Id in format string (no. 1) requires 'ptrdiff_t *' but the argument type is 'size_t * {aka unsigned long long *}'.\n"
|
||||||
|
"[test.cpp:9]: (warning) %Iu in format string (no. 2) requires 'size_t *' but the argument type is 'ptrdiff_t * {aka long long *}'.\n"
|
||||||
|
"[test.cpp:10]: (warning) %I32u in format string (no. 2) requires 'unsigned __int32 *' but the argument type is '__int32 * {aka int *}'.\n"
|
||||||
|
"[test.cpp:11]: (warning) %I32d in format string (no. 1) requires '__int32 *' but the argument type is 'unsigned __int32 * {aka unsigned int *}'.\n"
|
||||||
|
"[test.cpp:12]: (warning) %I64u in format string (no. 2) requires 'unsigned __int64 *' but the argument type is '__int64 * {aka long long *}'.\n"
|
||||||
|
"[test.cpp:13]: (warning) %I64d in format string (no. 1) requires '__int64 *' but the argument type is 'unsigned __int64 * {aka unsigned long long *}'.\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo() {\n"
|
||||||
|
" size_t s;\n"
|
||||||
|
" int i;\n"
|
||||||
|
" scanf(\"%I\", &s);\n"
|
||||||
|
" scanf(\"%I6\", &s);\n"
|
||||||
|
" scanf(\"%I6x\", &s);\n"
|
||||||
|
" scanf(\"%I16\", &s);\n"
|
||||||
|
" scanf(\"%I16x\", &s);\n"
|
||||||
|
" scanf(\"%I32\", &s);\n"
|
||||||
|
" scanf(\"%I64\", &s);\n"
|
||||||
|
" scanf(\"%I%i\", &s, &i);\n"
|
||||||
|
" scanf(\"%I6%i\", &s, &i);\n"
|
||||||
|
" scanf(\"%I6x%i\", &s, &i);\n"
|
||||||
|
" scanf(\"%I16%i\", &s, &i);\n"
|
||||||
|
" scanf(\"%I16x%i\", &s, &i);\n"
|
||||||
|
" scanf(\"%I32%i\", &s, &i);\n"
|
||||||
|
" scanf(\"%I64%i\", &s, &i);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:4]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||||
|
"[test.cpp:5]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||||
|
"[test.cpp:6]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||||
|
"[test.cpp:7]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||||
|
"[test.cpp:8]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||||
|
"[test.cpp:9]: (warning) 'I32' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||||
|
"[test.cpp:10]: (warning) 'I64' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||||
|
"[test.cpp:11]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||||
|
"[test.cpp:12]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||||
|
"[test.cpp:13]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||||
|
"[test.cpp:14]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||||
|
"[test.cpp:15]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||||
|
"[test.cpp:16]: (warning) 'I32' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||||
|
"[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
|
void testMicrosoftCStringFormatArguments() { // ticket #4920
|
||||||
check("void foo() {\n"
|
check("void foo() {\n"
|
||||||
" unsigned __int32 u32;\n"
|
" unsigned __int32 u32;\n"
|
||||||
|
@ -2289,6 +2367,42 @@ private:
|
||||||
ASSERT_EQUALS("[test.cpp:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'.\n"
|
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) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'int'.\n"
|
||||||
"[test.cpp:5]: (warning) _snwprintf_s format string requires 2 parameters but 3 are given.\n", errout.str());
|
"[test.cpp:5]: (warning) _snwprintf_s format string requires 2 parameters but 3 are given.\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo(FILE * fp) {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" unsigned int u;\n"
|
||||||
|
" _ftprintf_s(fp, _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) _ftprintf_s format string requires 2 parameters but 3 are given.\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo(FILE * fp) {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" unsigned int u;\n"
|
||||||
|
" _ftprintf_s(fp, _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) _ftprintf_s format string requires 2 parameters but 3 are given.\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo(FILE * fp) {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" unsigned int u;\n"
|
||||||
|
" fprintf_s(fp, \"%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) fprintf_s format string requires 2 parameters but 3 are given.\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo(FILE * fp) {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" unsigned int u;\n"
|
||||||
|
" fwprintf_s(fp, L\"%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) fwprintf_s format string requires 2 parameters but 3 are given.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void testMicrosoftSecureScanfArgument() {
|
void testMicrosoftSecureScanfArgument() {
|
||||||
|
@ -2376,6 +2490,46 @@ private:
|
||||||
"[test.cpp:6]: (warning) %u in format string (no. 3) requires 'unsigned int *' but the argument type is '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) swscanf_s format string requires 6 parameters but 7 are given.\n", errout.str());
|
"[test.cpp:6]: (warning) swscanf_s format string requires 6 parameters but 7 are given.\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo(FILE * fp) {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" unsigned int u;\n"
|
||||||
|
" TCHAR str[10];\n"
|
||||||
|
" _ftscanf_s(fp, _T(\"%s %d %u %[a-z]\"), str, 10, &u, &i, str, 10, 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) _ftscanf_s format string requires 6 parameters but 7 are given.\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo(FILE * fp) {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" unsigned int u;\n"
|
||||||
|
" TCHAR str[10];\n"
|
||||||
|
" _ftscanf_s(fp, _T(\"%s %d %u %[a-z]\"), str, 10, &u, &i, str, 10, 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) _ftscanf_s format string requires 6 parameters but 7 are given.\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo(FILE * fp) {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" unsigned int u;\n"
|
||||||
|
" char str[10];\n"
|
||||||
|
" fscanf_s(fp, \"%s %d %u %[a-z]\", str, 10, &u, &i, str, 10, 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) fscanf_s format string requires 6 parameters but 7 are given.\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo(FILE * fp) {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" unsigned int u;\n"
|
||||||
|
" wchar_t str[10];\n"
|
||||||
|
" fwscanf_s(fp, L\"%s %d %u %[a-z]\", str, 10, &u, &i, str, 10, 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) fwscanf_s format string requires 6 parameters but 7 are given.\n", errout.str());
|
||||||
|
|
||||||
check("void foo() {\n"
|
check("void foo() {\n"
|
||||||
" WCHAR msStr1[5] = {0};\n"
|
" WCHAR msStr1[5] = {0};\n"
|
||||||
" wscanf_s(L\"%4[^-]\", msStr1, _countof(msStr1));\n"
|
" wscanf_s(L\"%4[^-]\", msStr1, _countof(msStr1));\n"
|
||||||
|
|
Loading…
Reference in New Issue