Fixed #3373 (False posititive: incorrect %* handling in sscanf)
This commit is contained in:
parent
6763e596b9
commit
9a84c5845a
|
@ -173,13 +173,22 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
|
||||||
if (*i == '%') {
|
if (*i == '%') {
|
||||||
percent = !percent;
|
percent = !percent;
|
||||||
} else if (percent) {
|
} else if (percent) {
|
||||||
|
percent = false;
|
||||||
|
|
||||||
|
bool _continue = false;
|
||||||
while (!std::isalpha(*i)) {
|
while (!std::isalpha(*i)) {
|
||||||
if (*i == '*')
|
if (*i == '*') {
|
||||||
|
if (scan)
|
||||||
|
_continue = true;
|
||||||
|
else
|
||||||
argListTok = argListTok->nextArgument();
|
argListTok = argListTok->nextArgument();
|
||||||
|
}
|
||||||
++i;
|
++i;
|
||||||
if (!argListTok || i == formatString.end())
|
if (!argListTok || i == formatString.end())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (_continue)
|
||||||
|
continue;
|
||||||
|
|
||||||
if ((*i == 'n' || *i == 's' || scan) && (!scan || value == 0)) {
|
if ((*i == 'n' || *i == 's' || scan) && (!scan || value == 0)) {
|
||||||
if ((value == 0 && argListTok->str() == "0") || (Token::Match(argListTok, "%var%") && argListTok->varId() > 0)) {
|
if ((value == 0 && argListTok->str() == "0") || (Token::Match(argListTok, "%var%") && argListTok->varId() > 0)) {
|
||||||
|
@ -191,8 +200,6 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
|
||||||
argListTok = argListTok->nextArgument(); // Find next argument
|
argListTok = argListTok->nextArgument(); // Find next argument
|
||||||
if (!argListTok)
|
if (!argListTok)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
percent = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1285,6 +1285,7 @@ void CheckOther::checkWrongPrintfScanfArguments()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count format string parameters..
|
// Count format string parameters..
|
||||||
|
bool scan = Token::Match(tok, "sscanf|fscanf|scanf");
|
||||||
unsigned int numFormat = 0;
|
unsigned int numFormat = 0;
|
||||||
bool percent = false;
|
bool percent = false;
|
||||||
for (std::string::iterator i = formatString.begin(); i != formatString.end(); ++i) {
|
for (std::string::iterator i = formatString.begin(); i != formatString.end(); ++i) {
|
||||||
|
@ -1302,25 +1303,33 @@ void CheckOther::checkWrongPrintfScanfArguments()
|
||||||
if (i == formatString.end())
|
if (i == formatString.end())
|
||||||
break;
|
break;
|
||||||
} else if (percent) {
|
} else if (percent) {
|
||||||
|
percent = false;
|
||||||
|
|
||||||
|
bool _continue = false;
|
||||||
while (i != formatString.end() && !std::isalpha(*i)) {
|
while (i != formatString.end() && !std::isalpha(*i)) {
|
||||||
if (*i == '*')
|
if (*i == '*') {
|
||||||
|
if (scan)
|
||||||
|
_continue = true;
|
||||||
|
else
|
||||||
numFormat++;
|
numFormat++;
|
||||||
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
if (i == formatString.end())
|
if (i == formatString.end())
|
||||||
break;
|
break;
|
||||||
|
if (_continue)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (*i != 'm') // %m is a non-standard extension that requires no parameter
|
if (*i != 'm') // %m is a non-standard extension that requires no parameter
|
||||||
numFormat++;
|
numFormat++;
|
||||||
|
|
||||||
percent = false;
|
// TODO: Perform type checks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count printf/scanf parameters..
|
// Count printf/scanf parameters..
|
||||||
unsigned int numFunction = 0;
|
unsigned int numFunction = 0;
|
||||||
while (argListTok) {
|
while (argListTok) {
|
||||||
// TODO: Perform type checks
|
|
||||||
numFunction++;
|
numFunction++;
|
||||||
argListTok = argListTok->nextArgument(); // Find next argument
|
argListTok = argListTok->nextArgument(); // Find next argument
|
||||||
}
|
}
|
||||||
|
|
|
@ -1587,6 +1587,11 @@ private:
|
||||||
" sscanf(dummy, \"%d%d\", foo(iVal), iVal);\n"
|
" sscanf(dummy, \"%d%d\", foo(iVal), iVal);\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (error) Possible null pointer dereference: iVal\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (error) Possible null pointer dereference: iVal\n", errout.str());
|
||||||
|
|
||||||
|
check("void f(char* dummy) {\n"
|
||||||
|
" sscanf(dummy, \"%*d%u\", 0);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (error) Null pointer dereference\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void nullpointer_in_return() {
|
void nullpointer_in_return() {
|
||||||
|
|
|
@ -89,6 +89,7 @@ private:
|
||||||
TEST_CASE(testScanf2);
|
TEST_CASE(testScanf2);
|
||||||
TEST_CASE(testScanf3);
|
TEST_CASE(testScanf3);
|
||||||
|
|
||||||
|
TEST_CASE(testScanfArgument);
|
||||||
TEST_CASE(testPrintfArgument);
|
TEST_CASE(testPrintfArgument);
|
||||||
|
|
||||||
TEST_CASE(trac1132);
|
TEST_CASE(trac1132);
|
||||||
|
@ -1957,6 +1958,47 @@ private:
|
||||||
ASSERT_EQUALS("[test.cpp:7]: (warning) fscanf format string has 0 parameters but 1 are given\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:7]: (warning) fscanf format string has 0 parameters but 1 are given\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testScanfArgument() {
|
||||||
|
check("void foo() {\n"
|
||||||
|
" scanf(\"%1d\", &foo);\n"
|
||||||
|
" sscanf(bar, \"%1d\", &foo);\n"
|
||||||
|
" scanf(\"%1u%1u\", &foo, bar());\n"
|
||||||
|
" scanf(\"%*1x %1x %29s\", &count, KeyName);\n" // #3373
|
||||||
|
"}\n",
|
||||||
|
"test.cpp",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void foo() {\n"
|
||||||
|
" scanf(\"\", &foo);\n"
|
||||||
|
" scanf(\"%1d\", &foo, &bar);\n"
|
||||||
|
" fscanf(bar, \"%1d\", &foo, &bar);\n"
|
||||||
|
" scanf(\"%*1x %1x %29s\", &count, KeyName, foo);\n"
|
||||||
|
"}\n",
|
||||||
|
"test.cpp",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (warning) scanf format string has 0 parameters but 1 are given\n"
|
||||||
|
"[test.cpp:3]: (warning) scanf format string has 1 parameters but 2 are given\n"
|
||||||
|
"[test.cpp:4]: (warning) fscanf format string has 1 parameters but 2 are given\n"
|
||||||
|
"[test.cpp:5]: (warning) scanf format string has 2 parameters but 3 are given\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo() {\n"
|
||||||
|
" scanf(\"%1d\");\n"
|
||||||
|
" scanf(\"%1u%1u\", bar());\n"
|
||||||
|
" sscanf(bar, \"%1d%1d\", &foo);\n"
|
||||||
|
" scanf(\"%*1x %1x %29s\", &count);\n"
|
||||||
|
"}\n",
|
||||||
|
"test.cpp",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (error) scanf format string has 1 parameters but only 0 are given\n"
|
||||||
|
"[test.cpp:3]: (error) scanf format string has 2 parameters but only 1 are given\n"
|
||||||
|
"[test.cpp:4]: (error) sscanf format string has 2 parameters but only 1 are given\n"
|
||||||
|
"[test.cpp:5]: (error) scanf format string has 2 parameters but only 1 are given\n", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void testPrintfArgument() {
|
void testPrintfArgument() {
|
||||||
check("void foo() {\n"
|
check("void foo() {\n"
|
||||||
" printf(\"%u\");\n"
|
" printf(\"%u\");\n"
|
||||||
|
|
Loading…
Reference in New Issue