Fixed #4964 (printf format argument check only supports simple variables)

This commit is contained in:
Robert Reif 2013-08-20 06:16:31 +02:00 committed by Daniel Marjamäki
parent bf8a786265
commit 707dfb4eea
3 changed files with 44 additions and 3 deletions

View File

@ -555,9 +555,10 @@ void CheckIO::checkWrongPrintfScanfArguments()
}
// Perform type checks
if (argListTok && Token::Match(argListTok->next(), "[,)]")) { // We can currently only check the type of arguments matching this simple pattern.
const Variable *variableInfo = argListTok->variable();
const Token* varTypeTok = variableInfo ? variableInfo->typeStartToken() : NULL;
const Variable *variableInfo;
const Token *varTypeTok;
if (getArgumentInfo(argListTok, &variableInfo, &varTypeTok)) {
if (varTypeTok && varTypeTok->str() == "static")
varTypeTok = varTypeTok->next();
@ -735,6 +736,33 @@ void CheckIO::checkWrongPrintfScanfArguments()
}
}
// We can currently only check the type of arguments matching these simple patterns:
// var
// var.var
// var[...]
//
/// @todo add more complex variables, lietrals, functions, and generic expressions
bool CheckIO::getArgumentInfo(const Token * tok, const Variable **var, const Token **typeTok) const
{
if (tok && (Token::Match(tok->next(), "[,)]") ||
Token::Match(tok->next(), ". %var% [,)]") ||
(Token::simpleMatch(tok->next(), "[") && Token::Match(tok->linkAt(1)->next(), "[,)]")))) {
if (tok->next()->str() == ".")
tok = tok->tokAt(2);
const Variable *variableInfo = tok->variable();
const Token *varTypeTok = variableInfo ? variableInfo->typeStartToken() : NULL;
*var = variableInfo;
*typeTok = varTypeTok;
return true;
}
return false;
}
void CheckIO::wrongPrintfScanfArgumentsError(const Token* tok,
const std::string &functionName,
unsigned int numFormat,

View File

@ -70,6 +70,8 @@ public:
void checkWrongPrintfScanfArguments();
private:
bool getArgumentInfo(const Token *tok, const Variable **var, const Token **typeTok) const;
// Reporting errors..
void coutCerrMisusageError(const Token* tok, const std::string& streamName);
void fflushOnInputStreamError(const Token *tok, const std::string &varname);

View File

@ -793,6 +793,17 @@ private:
"[test.cpp:5]: (warning) %llu in format string (no. 1) requires an unsigned long long integer given in the argument list.\n"
"[test.cpp:6]: (warning) %lx in format string (no. 1) requires a long integer given in the argument list.\n"
"[test.cpp:7]: (warning) %llx in format string (no. 1) requires a long long integer given in the argument list.\n", errout.str());
check("class Foo {\n"
" double d;\n"
"};\n"
"int a[10];\n"
"void foo(const Foo* foo) {\n"
" printf(\"%d\", foo->d);\n"
" printf(\"%f\", a[0]);\n"
"}");
ASSERT_EQUALS("[test.cpp:6]: (warning) %d in format string (no. 1) requires a signed integer given in the argument list.\n"
"[test.cpp:7]: (warning) %f in format string (no. 1) requires a floating point number given in the argument list.\n", errout.str());
}
void testPosixPrintfScanfParameterPosition() { // #4900 - No support for parameters in format strings