From c666a9662bb1b50e7afe79aeea6d188d3b9c558e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Mon, 11 Jan 2010 21:18:07 +0100 Subject: [PATCH] BufferOverrun: negative index is out of bounds --- lib/checkbufferoverrun.cpp | 12 ++++++------ lib/tokenize.cpp | 2 +- test/testbufferoverrun.cpp | 12 ++++++++++++ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index c98980177..b7d9905ab 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -167,7 +167,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const char *varname[], con if (Token::Match(tok, "%varid% [ %num% ]", varid)) { int index = std::strtol(tok->strAt(2), NULL, 10); - if (index >= size) + if (index < 0 || index >= size) { 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())) { int index = std::strtol(tok->strAt(2 + varc), NULL, 10); - if (index >= size) + if (index < 0 || index >= size) { 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)) { int index = std::strtol(tok->strAt(3), NULL, 10); - if (index >= size) + if (index < 0 || index >= size) { 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())) { 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); } @@ -267,7 +267,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const char *varname[], con else if (tokSz->isNumber()) { const char *num = tok->strAt(6); - if (std::atoi(num) > total_size) + if (std::atoi(num) < 0 || std::atoi(num) > total_size) { 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())) { 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); } diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 533fba021..6c4eb6a3a 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -696,7 +696,7 @@ bool Tokenizer::tokenize(std::istream &code, const char FileName[]) // Combine "- %num%" .. 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()->deleteNext(); diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index 24f4f547e..6009ecb11 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -96,6 +96,7 @@ private: TEST_CASE(array_index_multidim); TEST_CASE(array_index_switch_in_for); TEST_CASE(array_index_calculation); + TEST_CASE(array_index_negative); TEST_CASE(buffer_overrun_1); 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()); } + 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() { check("void f()\n"