Fix #826 (False positive: sprintf with "f%s")

http://sourceforge.net/apps/trac/cppcheck/ticket/826
This commit is contained in:
Reijo Tomperi 2009-10-18 13:58:48 +03:00
parent 34fe032dbe
commit aca743c9ed
2 changed files with 60 additions and 92 deletions

View File

@ -806,33 +806,35 @@ void CheckBufferOverrun::bufferOverrun()
int CheckBufferOverrun::countSprintfLength(const std::string &input_string, const std::list<const Token*> &parameters) int CheckBufferOverrun::countSprintfLength(const std::string &input_string, const std::list<const Token*> &parameters)
{ {
int flag = 1; bool percentCharFound = false;
int second_flag = 0; // This is to check for % int input_string_size = 1;
int input_string_size = 0; bool handleNextParameter = false;
int on_on_next = 0;
std::string digits_string = ""; std::string digits_string = "";
int digits = 0; bool i_d_x_f_found = false;
int check_for_i_d_x_f = 0;
std::list<const Token*>::const_iterator paramIter = parameters.begin(); std::list<const Token*>::const_iterator paramIter = parameters.begin();
unsigned int parameterLength = 0; unsigned int parameterLength = 0;
for (std::string::size_type i = 0; i != input_string.length(); i++) for (std::string::size_type i = 0; i < input_string.length(); ++i)
{ {
if (input_string[i] == '\\')
{
if (input_string[i+1] == '0')
break;
if (on_on_next == 1) ++input_string_size;
{ ++i;
flag = 1; continue;
on_on_next = 0;
} }
if (percentCharFound)
{
switch (input_string[i]) switch (input_string[i])
{ {
case '\\':
if (input_string[i+1] == '0') break;
case 'f': case 'f':
case 'x': case 'x':
case 'X': case 'X':
case 'd': case 'd':
case 'i': case 'i':
check_for_i_d_x_f = 1; i_d_x_f_found = true;
case 'c': case 'c':
case 'e': case 'e':
case 'E': case 'E':
@ -841,47 +843,34 @@ int CheckBufferOverrun::countSprintfLength(const std::string &input_string, cons
case 'u': case 'u':
case 'p': case 'p':
case 'n': case 'n':
if (flag == 0) handleNextParameter = true;
{
on_on_next = 1;
if (paramIter != parameters.end()) ++paramIter; if (paramIter != parameters.end()) ++paramIter;
}
break; break;
case 's': case 's':
if (flag == 0)
{
if (paramIter != parameters.end() && *paramIter && (*paramIter)->str()[0] == '"') if (paramIter != parameters.end() && *paramIter && (*paramIter)->str()[0] == '"')
parameterLength = Token::getStrLength(*paramIter); parameterLength = Token::getStrLength(*paramIter);
on_on_next = 1; handleNextParameter = true;
if (paramIter != parameters.end()) ++paramIter; if (paramIter != parameters.end()) ++paramIter;
}
break; break;
}
}
if (input_string[i] == '%')
case '%': percentCharFound = !percentCharFound;
if (flag == 1) flag = 0; else if (percentCharFound)
else
{ {
flag = 1; digits_string.append(1, input_string[i]);
}
if (!percentCharFound)
input_string_size++; input_string_size++;
second_flag = 1;
}
break;
}
if (flag && !second_flag) input_string_size++; if (handleNextParameter)
else
digits_string += input_string[i];
if (on_on_next == 1 && flag == 0)
{ {
digits_string = digits_string.substr(1, digits_string.size()); unsigned int tempDigits = std::abs(std::atoi(digits_string.c_str()));
unsigned int tempDigits = 0; if (i_d_x_f_found)
if (check_for_i_d_x_f == 1) tempDigits = std::max(static_cast<int>(tempDigits), 1);
tempDigits = std::max(std::abs(std::atoi(digits_string.c_str())), 1);
else
tempDigits = std::abs(std::atoi(digits_string.c_str()));
if (parameterLength > 0 && digits_string.find('.') != std::string::npos) if (parameterLength > 0 && digits_string.find('.') != std::string::npos)
{ {
@ -896,45 +885,21 @@ int CheckBufferOverrun::countSprintfLength(const std::string &input_string, cons
} }
if (tempDigits < parameterLength) if (tempDigits < parameterLength)
digits += parameterLength; input_string_size += parameterLength;
else if (parameterLength <= tempDigits) else if (parameterLength <= tempDigits)
digits += tempDigits; input_string_size += tempDigits;
else else
digits += parameterLength - tempDigits; input_string_size += parameterLength - tempDigits;
parameterLength = 0; parameterLength = 0;
digits_string = ""; digits_string = "";
check_for_i_d_x_f = 0; i_d_x_f_found = false;
percentCharFound = false;
handleNextParameter = false;
} }
second_flag = 0;
} }
// A second iteration through the string to deal with /'s return input_string_size;
std::string::size_type j = 0;
while (j < input_string.size())
{
if (input_string[j] == '\\' && input_string[j+1] == '0')
{
input_string_size++;
break;
}
if (input_string[j] == '\\')
{
input_string_size--;
j += 2;
continue;
}
j++;
}
return input_string_size + 1 + digits;
} }

View File

@ -1075,13 +1075,16 @@ private:
ASSERT_EQUALS(2, CheckBufferOverrun::countSprintfLength("%1d", unknownParameter)); ASSERT_EQUALS(2, CheckBufferOverrun::countSprintfLength("%1d", unknownParameter));
ASSERT_EQUALS(3, CheckBufferOverrun::countSprintfLength("%2.2d", unknownParameter)); ASSERT_EQUALS(3, CheckBufferOverrun::countSprintfLength("%2.2d", unknownParameter));
ASSERT_EQUALS(1, CheckBufferOverrun::countSprintfLength("%s", unknownParameter)); ASSERT_EQUALS(1, CheckBufferOverrun::countSprintfLength("%s", unknownParameter));
ASSERT_EQUALS(2, CheckBufferOverrun::countSprintfLength("f%s", unknownParameter));
ASSERT_EQUALS(1, CheckBufferOverrun::countSprintfLength("%-s", unknownParameter)); ASSERT_EQUALS(1, CheckBufferOverrun::countSprintfLength("%-s", unknownParameter));
ASSERT_EQUALS(6, CheckBufferOverrun::countSprintfLength("%-5s", unknownParameter)); ASSERT_EQUALS(6, CheckBufferOverrun::countSprintfLength("%-5s", unknownParameter));
ASSERT_EQUALS(2, CheckBufferOverrun::countSprintfLength("\\\"", unknownParameter)); ASSERT_EQUALS(2, CheckBufferOverrun::countSprintfLength("\\\"", unknownParameter));
ASSERT_EQUALS(7, CheckBufferOverrun::countSprintfLength("Hello \0Text", unknownParameter)); ASSERT_EQUALS(7, CheckBufferOverrun::countSprintfLength("Hello \\0Text", unknownParameter));
ASSERT_EQUALS(1, CheckBufferOverrun::countSprintfLength("\\0", unknownParameter));
ASSERT_EQUALS(2, CheckBufferOverrun::countSprintfLength("%%", unknownParameter)); ASSERT_EQUALS(2, CheckBufferOverrun::countSprintfLength("%%", unknownParameter));
ASSERT_EQUALS(3, CheckBufferOverrun::countSprintfLength("%d%d", unknownParameter)); ASSERT_EQUALS(3, CheckBufferOverrun::countSprintfLength("%d%d", unknownParameter));
ASSERT_EQUALS(10, CheckBufferOverrun::countSprintfLength("\\\\\\\\Hello%d \0Text\\\\\\\\", unknownParameter)); ASSERT_EQUALS(3, CheckBufferOverrun::countSprintfLength("\\\\a%s\\0a", unknownParameter));
ASSERT_EQUALS(10, CheckBufferOverrun::countSprintfLength("\\\\\\\\Hello%d \\0Text\\\\\\\\", unknownParameter));
ASSERT_EQUALS(4, CheckBufferOverrun::countSprintfLength("%%%%%d", unknownParameter)); ASSERT_EQUALS(4, CheckBufferOverrun::countSprintfLength("%%%%%d", unknownParameter));
Token strTok; Token strTok;