Fixed #819 (array index out of bounds not detected for multidimension arrays)

This commit is contained in:
Daniel Marjamäki 2010-04-23 16:26:40 +02:00
parent f4ce5a37d7
commit a3b781a181
3 changed files with 57 additions and 25 deletions

View File

@ -82,13 +82,22 @@ void CheckBufferOverrun::arrayIndexOutOfBounds(int size, int index)
reportError(_callStack, severity, "arrayIndexOutOfBounds", "Array index out of bounds"); reportError(_callStack, severity, "arrayIndexOutOfBounds", "Array index out of bounds");
} }
void CheckBufferOverrun::arrayIndexOutOfBounds(const Token *tok, const ArrayInfo &arrayInfo, int index) void CheckBufferOverrun::arrayIndexOutOfBounds(const Token *tok, const ArrayInfo &arrayInfo, const std::vector<int> &index)
{ {
std::ostringstream oss; std::ostringstream oss;
oss << "Array '" << arrayInfo.varname; oss << "Array '" << arrayInfo.varname;
for (unsigned int i = 0; i < arrayInfo.num.size(); ++i) for (unsigned int i = 0; i < arrayInfo.num.size(); ++i)
oss << "[" << arrayInfo.num[i] << "]"; oss << "[" << arrayInfo.num[i] << "]";
oss << "' index " << index << " out of bounds"; oss << "' index ";
if (index.size() == 1)
oss << index[0];
else
{
oss << arrayInfo.varname;
for (unsigned int i = 0; i < index.size(); ++i)
oss << "[" << index[i] << "]";
}
oss << " out of bounds";
reportError(tok, Severity::error, "arrayIndexOutOfBounds", oss.str().c_str()); reportError(tok, Severity::error, "arrayIndexOutOfBounds", oss.str().c_str());
} }
@ -860,19 +869,51 @@ void CheckBufferOverrun::checkScope(const Token *tok, const ArrayInfo &arrayInfo
else if (Token::Match(tok, "%varid% [ %num% ]", arrayInfo.varid)) else if (Token::Match(tok, "%varid% [ %num% ]", arrayInfo.varid))
{ {
const int index = MathLib::toLongNumber(tok->strAt(2)); std::vector<int> indexes;
if (index >= (int)arrayInfo.num[0]) for (const Token *tok2 = tok->next(); Token::Match(tok2, "[ %num% ]"); tok2 = tok2->tokAt(3))
{ {
const int index = MathLib::toLongNumber(tok2->strAt(1));
if (index < 0)
{
indexes.clear();
break;
}
indexes.push_back(index);
}
if (indexes.size() == arrayInfo.num.size())
{
// Check if the indexes point outside the whole array..
// char a[10][10];
// a[0][20] <-- ok.
// a[9][20] <-- error.
// total number of elements of array..
unsigned int totalElements = 1;
// total index..
unsigned int totalIndex = 0;
// calculate the totalElements and totalIndex..
for (unsigned int i = 0; i < indexes.size(); ++i)
{
unsigned int ri = indexes.size() - 1 - i;
totalIndex += indexes[ri] * totalElements;
totalElements *= arrayInfo.num[ri];
}
// just taking the address? // just taking the address?
const bool addr(Token::Match(tok->previous(), "[.&]") || const bool addr(Token::Match(tok->previous(), "[.&]") ||
Token::simpleMatch(tok->tokAt(-2), "& (")); Token::simpleMatch(tok->tokAt(-2), "& ("));
// it's ok to take the address of the element past the array // Is totalIndex in bounds?
if (!(addr && index == (int)arrayInfo.num[0])) if (totalIndex > totalElements || (!addr && totalIndex == totalElements))
arrayIndexOutOfBounds(tok, arrayInfo, index); {
arrayIndexOutOfBounds(tok, arrayInfo, indexes);
} }
} }
}
// cin.. // cin..
else if (Token::Match(tok, "cin >> %varid% ;", arrayInfo.varid)) else if (Token::Match(tok, "cin >> %varid% ;", arrayInfo.varid))
{ {
@ -1688,7 +1729,9 @@ private:
CheckBufferOverrun *checkBufferOverrun = dynamic_cast<CheckBufferOverrun *>(c->owner); CheckBufferOverrun *checkBufferOverrun = dynamic_cast<CheckBufferOverrun *>(c->owner);
if (checkBufferOverrun) if (checkBufferOverrun)
{ {
checkBufferOverrun->arrayIndexOutOfBounds(tok, ai, c->value); std::vector<int> index;
index.push_back(c->value);
checkBufferOverrun->arrayIndexOutOfBounds(tok, ai, index);
break; break;
} }
} }

View File

@ -171,7 +171,7 @@ public:
void arrayIndexOutOfBounds(const Token *tok, int size, int index); void arrayIndexOutOfBounds(const Token *tok, int size, int index);
void arrayIndexOutOfBounds(int size, int index); void arrayIndexOutOfBounds(int size, int index);
void arrayIndexOutOfBounds(const Token *tok, const ArrayInfo &arrayInfo, int index); void arrayIndexOutOfBounds(const Token *tok, const ArrayInfo &arrayInfo, const std::vector<int> &index);
void bufferOverrun(const Token *tok, const std::string &varnames = ""); void bufferOverrun(const Token *tok, const std::string &varnames = "");
void dangerousStdCin(const Token *tok); void dangerousStdCin(const Token *tok);
void strncatUsage(const Token *tok); void strncatUsage(const Token *tok);

View File

@ -922,46 +922,35 @@ private:
" char a[2][2];\n" " char a[2][2];\n"
" a[2][1] = 'a';\n" " a[2][1] = 'a';\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a[2][2]' index 2 out of bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a[2][2]' index a[2][1] out of bounds\n", errout.str());
check("void f()\n" check("void f()\n"
"{\n" "{\n"
" char a[2][2];\n" " char a[2][2];\n"
" a[1][2] = 'a';\n" " a[1][2] = 'a';\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); // catch changes ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a[2][2]' index a[1][2] out of bounds\n", errout.str());
TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a[2][2]' index 2 out of bounds\n", errout.str());
check("void f()\n" check("void f()\n"
"{\n" "{\n"
" char a[2][2][2];\n" " char a[2][2][2];\n"
" a[2][1][1] = 'a';\n" " a[2][1][1] = 'a';\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a[2][2][2]' index 2 out of bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a[2][2][2]' index a[2][1][1] out of bounds\n", errout.str());
check("void f()\n" check("void f()\n"
"{\n" "{\n"
" char a[2][2][2];\n" " char a[2][2][2];\n"
" a[1][2][1] = 'a';\n" " a[1][2][1] = 'a';\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); // catch changes ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a[2][2][2]' index a[1][2][1] out of bounds\n", errout.str());
TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Array index out of bounds\n", errout.str());
check("void f()\n" check("void f()\n"
"{\n" "{\n"
" char a[2][2][2];\n" " char a[2][2][2];\n"
" a[1][1][2] = 'a';\n" " a[1][1][2] = 'a';\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); // catch changes ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a[2][2][2]' index a[1][1][2] out of bounds\n", errout.str());
TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Array index out of bounds\n", errout.str());
check("void f()\n"
"{\n"
" char a[2][2][2];\n"
" a[1][1][2] = 'a';\n"
"}\n");
ASSERT_EQUALS("", errout.str()); // catch changes
TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Array index out of bounds\n", errout.str());
} }
void array_index_switch_in_for() void array_index_switch_in_for()