Fixed #4902 (printf and scanf format checks don't support microsoft %I, %I32 and %I64 extensions)

This commit is contained in:
Robert Reif 2013-08-10 12:37:31 +02:00 committed by Daniel Marjamäki
parent 5aa79198e6
commit 56d8073d0f
3 changed files with 42 additions and 18 deletions

View File

@ -682,32 +682,23 @@ void CheckIO::checkWrongPrintfScanfArguments()
} }
break; break;
case 'I': // Microsoft extension: I for size_t and ptrdiff_t, I32 for __int32, and I64 for __int64 case 'I': // Microsoft extension: I for size_t and ptrdiff_t, I32 for __int32, and I64 for __int64
if (i != formatString.end()) { if ((*(i+1) == '3' && *(i+2) == '2') ||
if (isalpha(*(i+1))) { (*(i+1) == '6' && *(i+2) == '4')) {
specifier = *i++; specifier += *i++;
} else if (*(i+1) == '3' && *(i+2) == '2' && isalpha(*(i+3))) { specifier += *i++;
specifier = *i++;
specifier += *i++;
specifier += *i++;
} else if (*(i+1) == '6' && *(i+2) == '4' && isalpha(*(i+3))) {
specifier = *i++;
specifier += *i++;
specifier += *i++;
}
} }
break; // fallthrough
case 'j': // intmax_t or uintmax_t case 'j': // intmax_t or uintmax_t
case 'z': // size_t case 'z': // size_t
case 't': // ptrdiff_t case 't': // ptrdiff_t
case 'L': // long double case 'L': // long double
// Expect an alphabetical character after these specifiers // Expect an alphabetical character after these specifiers
if (i != formatString.end() && !isalpha(*(i+1))) { if (i != formatString.end() && !isalpha(*(i+1))) {
std::string modifier; specifier += *i;
modifier += *i; invalidLengthModifierError(tok, numFormat, specifier);
invalidLengthModifierError(tok, numFormat, modifier);
done = true; done = true;
} else { } else {
specifier = *i++; specifier += *i++;
} }
break; break;
default: default:

View File

@ -92,7 +92,7 @@ private:
void invalidPrintfArgTypeError_uint(const Token* tok, unsigned int numFormat, const std::string& specifier); void invalidPrintfArgTypeError_uint(const Token* tok, unsigned int numFormat, const std::string& specifier);
void invalidPrintfArgTypeError_sint(const Token* tok, unsigned int numFormat, const std::string& specifier); void invalidPrintfArgTypeError_sint(const Token* tok, unsigned int numFormat, const std::string& specifier);
void invalidPrintfArgTypeError_float(const Token* tok, unsigned int numFormat, const std::string& specifier); void invalidPrintfArgTypeError_float(const Token* tok, unsigned int numFormat, const std::string& specifier);
void invalidLengthModifierError(const Token* tok, unsigned int numFormat,const std::string& modifier); void invalidLengthModifierError(const Token* tok, unsigned int numFormat, const std::string& modifier);
void invalidScanfFormatWidthError(const Token* tok, unsigned int numFormat, int width, const Variable *var); void invalidScanfFormatWidthError(const Token* tok, unsigned int numFormat, int width, const Variable *var);
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {

View File

@ -840,6 +840,39 @@ private:
"[test.cpp:11]: (warning) %I32d in format string (no. 1) requires a signed integer given in the argument list.\n" "[test.cpp:11]: (warning) %I32d in format string (no. 1) requires a signed integer given in the argument list.\n"
"[test.cpp:12]: (warning) %I64u in format string (no. 2) requires an unsigned integer given in the argument list.\n" "[test.cpp:12]: (warning) %I64u in format string (no. 2) requires an unsigned integer given in the argument list.\n"
"[test.cpp:13]: (warning) %I64d in format string (no. 1) requires a signed integer given in the argument list.\n", errout.str()); "[test.cpp:13]: (warning) %I64d in format string (no. 1) requires a signed integer given in the argument list.\n", errout.str());
check("void foo() {\n"
" size_t s;\n"
" int i;\n"
" printf(\"%I\", s);\n"
" printf(\"%I6\", s);\n"
" printf(\"%I6x\", s);\n"
" printf(\"%I16\", s);\n"
" printf(\"%I16x\", s);\n"
" printf(\"%I32\", s);\n"
" printf(\"%I64\", s);\n"
" printf(\"%I%i\", s, i);\n"
" printf(\"%I6%i\", s, i);\n"
" printf(\"%I6x%i\", s, i);\n"
" printf(\"%I16%i\", s, i);\n"
" printf(\"%I16x%i\", s, i);\n"
" printf(\"%I32%i\", s, i);\n"
" printf(\"%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 testlibrarycfg() { void testlibrarycfg() {