BufferOverrun: negative index is out of bounds

This commit is contained in:
Daniel Marjamäki 2010-01-11 21:18:07 +01:00
parent b8b6b0ec32
commit c666a9662b
3 changed files with 19 additions and 7 deletions

View File

@ -167,7 +167,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const char *varname[], con
if (Token::Match(tok, "%varid% [ %num% ]", varid)) if (Token::Match(tok, "%varid% [ %num% ]", varid))
{ {
int index = std::strtol(tok->strAt(2), NULL, 10); int index = std::strtol(tok->strAt(2), NULL, 10);
if (index >= size) if (index < 0 || index >= size)
{ {
arrayIndexOutOfBounds(tok, size, index); arrayIndexOutOfBounds(tok, size, index);
} }
@ -176,7 +176,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const char *varname[], con
else if (Token::Match(tok, std::string(varnames + " [ %num% ]").c_str())) else if (Token::Match(tok, std::string(varnames + " [ %num% ]").c_str()))
{ {
int index = std::strtol(tok->strAt(2 + varc), NULL, 10); int index = std::strtol(tok->strAt(2 + varc), NULL, 10);
if (index >= size) if (index < 0 || index >= size)
{ {
arrayIndexOutOfBounds(tok->tokAt(varc), size, index); arrayIndexOutOfBounds(tok->tokAt(varc), size, index);
} }
@ -203,7 +203,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const char *varname[], con
if (!tok->isName() && !Token::Match(tok, "[.&]") && Token::Match(tok->next(), "%varid% [ %num% ]", varid)) if (!tok->isName() && !Token::Match(tok, "[.&]") && Token::Match(tok->next(), "%varid% [ %num% ]", varid))
{ {
int index = std::strtol(tok->strAt(3), NULL, 10); int index = std::strtol(tok->strAt(3), NULL, 10);
if (index >= size) if (index < 0 || index >= size)
{ {
if (index > size || !Token::Match(tok->previous(), "& (")) if (index > size || !Token::Match(tok->previous(), "& ("))
{ {
@ -215,7 +215,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const char *varname[], con
else if (!tok->isName() && !Token::Match(tok, "[.&]") && Token::Match(tok->next(), std::string(varnames + " [ %num% ]").c_str())) else if (!tok->isName() && !Token::Match(tok, "[.&]") && Token::Match(tok->next(), std::string(varnames + " [ %num% ]").c_str()))
{ {
int index = std::strtol(tok->strAt(3 + varc), NULL, 10); int index = std::strtol(tok->strAt(3 + varc), NULL, 10);
if (index >= size) if (index < 0 || index >= size)
{ {
arrayIndexOutOfBounds(tok->tokAt(1 + varc), size, index); arrayIndexOutOfBounds(tok->tokAt(1 + varc), size, index);
} }
@ -267,7 +267,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const char *varname[], con
else if (tokSz->isNumber()) else if (tokSz->isNumber())
{ {
const char *num = tok->strAt(6); const char *num = tok->strAt(6);
if (std::atoi(num) > total_size) if (std::atoi(num) < 0 || std::atoi(num) > total_size)
{ {
bufferOverrun(tok); bufferOverrun(tok);
} }
@ -280,7 +280,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const char *varname[], con
Token::Match(tok->next(), std::string("( %var% , " + varnames + " , %num% )").c_str())) Token::Match(tok->next(), std::string("( %var% , " + varnames + " , %num% )").c_str()))
{ {
const char *num = tok->strAt(varc + 6); const char *num = tok->strAt(varc + 6);
if (std::atoi(num) > total_size) if (std::atoi(num) < 0 || std::atoi(num) > total_size)
{ {
bufferOverrun(tok); bufferOverrun(tok);
} }

View File

@ -696,7 +696,7 @@ bool Tokenizer::tokenize(std::istream &code, const char FileName[])
// Combine "- %num%" .. // Combine "- %num%" ..
for (Token *tok = _tokens; tok; tok = tok->next()) for (Token *tok = _tokens; tok; tok = tok->next())
{ {
if (Token::Match(tok, "[(+-*/=,] - %num%") && tok->strAt(2)[0] != '-') if (Token::Match(tok, "[([+-*/=,] - %num%") && tok->strAt(2)[0] != '-')
{ {
tok->next()->str(std::string("-") + tok->strAt(2)); tok->next()->str(std::string("-") + tok->strAt(2));
tok->next()->deleteNext(); tok->next()->deleteNext();

View File

@ -96,6 +96,7 @@ private:
TEST_CASE(array_index_multidim); TEST_CASE(array_index_multidim);
TEST_CASE(array_index_switch_in_for); TEST_CASE(array_index_switch_in_for);
TEST_CASE(array_index_calculation); TEST_CASE(array_index_calculation);
TEST_CASE(array_index_negative);
TEST_CASE(buffer_overrun_1); TEST_CASE(buffer_overrun_1);
TEST_CASE(buffer_overrun_2); TEST_CASE(buffer_overrun_2);
@ -838,6 +839,17 @@ private:
TODO_ASSERT_EQUALS("[test.cpp:5]: (error) Array index out of bounds\n", errout.str()); TODO_ASSERT_EQUALS("[test.cpp:5]: (error) Array index out of bounds\n", errout.str());
} }
void array_index_negative()
{
// #948 - array index out of bound not detected 'a[-1] = 0'
check("void f()\n"
"{\n"
" char data[8];\n"
" data[-1] = 0;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Array 'data[8]' index -1 out of bounds\n", errout.str());
}
void buffer_overrun_1() void buffer_overrun_1()
{ {
check("void f()\n" check("void f()\n"