Fixed #3893 (Improve check: Array index out of bounds not detected when down conting)

This commit is contained in:
Daniel Marjamäki 2012-06-16 17:44:51 +02:00
parent 89b1b4ea6e
commit 7d59d86ed6
2 changed files with 34 additions and 10 deletions

View File

@ -245,10 +245,11 @@ static bool bailoutIfSwitch(const Token *tok, const unsigned int varid)
* Parse for loop initialization statement. Look for a counter variable * Parse for loop initialization statement. Look for a counter variable
* \param tok [in] first token inside the parentheses * \param tok [in] first token inside the parentheses
* \param varid [out] varid of counter variable * \param varid [out] varid of counter variable
* \param varname [out] name of counter variable
* \param init_value [out] init value of counter variable * \param init_value [out] init value of counter variable
* \return success => pointer to the for loop condition. fail => 0 * \return success => pointer to the for loop condition. fail => 0
*/ */
static const Token *for_init(const Token *tok, unsigned int &varid, std::string &init_value) static const Token *for_init(const Token *tok, unsigned int &varid, std::string &varname, std::string &init_value)
{ {
if (Token::Match(tok, "%var% = %any% ;")) { if (Token::Match(tok, "%var% = %any% ;")) {
if (tok->tokAt(2)->isNumber()) { if (tok->tokAt(2)->isNumber()) {
@ -256,6 +257,7 @@ static const Token *for_init(const Token *tok, unsigned int &varid, std::string
} }
varid = tok->varId(); varid = tok->varId();
varname = tok->str();
tok = tok->tokAt(4); tok = tok->tokAt(4);
} else if (Token::Match(tok, "%type% %var% = %any% ;")) { } else if (Token::Match(tok, "%type% %var% = %any% ;")) {
if (tok->tokAt(3)->isNumber()) { if (tok->tokAt(3)->isNumber()) {
@ -263,6 +265,7 @@ static const Token *for_init(const Token *tok, unsigned int &varid, std::string
} }
varid = tok->next()->varId(); varid = tok->next()->varId();
varname = tok->next()->str();
tok = tok->tokAt(5); tok = tok->tokAt(5);
} else if (Token::Match(tok, "%type% %type% %var% = %any% ;")) { } else if (Token::Match(tok, "%type% %type% %var% = %any% ;")) {
if (tok->tokAt(4)->isNumber()) { if (tok->tokAt(4)->isNumber()) {
@ -270,6 +273,7 @@ static const Token *for_init(const Token *tok, unsigned int &varid, std::string
} }
varid = tok->tokAt(2)->varId(); varid = tok->tokAt(2)->varId();
varname = tok->tokAt(2)->str();
tok = tok->tokAt(6); tok = tok->tokAt(6);
} else } else
return 0; return 0;
@ -279,7 +283,7 @@ static const Token *for_init(const Token *tok, unsigned int &varid, std::string
/** Parse for condition */ /** Parse for condition */
static bool for_condition(const Token * const tok2, unsigned int varid, std::string &min_value, std::string &max_value, std::string &strindex, bool &maxMinFlipped) static bool for_condition(const Token * const tok2, unsigned int varid, std::string &min_value, std::string &max_value, bool &maxMinFlipped)
{ {
if (Token::Match(tok2, "%varid% < %num% ;", varid) || if (Token::Match(tok2, "%varid% < %num% ;", varid) ||
Token::Match(tok2, "%varid% != %num% ; ++ %varid%", varid) || Token::Match(tok2, "%varid% != %num% ; ++ %varid%", varid) ||
@ -305,8 +309,6 @@ static bool for_condition(const Token * const tok2, unsigned int varid, std::str
return false; return false;
} }
strindex = tok2->isName() ? tok2->str() : tok2->strAt(2);
return true; return true;
} }
@ -713,18 +715,31 @@ void CheckBufferOverrun::checkScopeForBody(const Token *tok, const ArrayInfo &ar
return; return;
} }
std::string counter_name;
unsigned int counter_varid = 0; unsigned int counter_varid = 0;
std::string min_counter_value; std::string counter_init_value;
std::string max_counter_value;
tok2 = for_init(tok2, counter_varid, min_counter_value); tok2 = for_init(tok2, counter_varid, counter_name, counter_init_value);
if (tok2 == 0 || counter_varid == 0) if (tok2 == 0 || counter_varid == 0)
return; return;
bool maxMinFlipped = false; bool maxMinFlipped = false;
std::string strindex; std::string min_counter_value = counter_init_value;
if (!for_condition(tok2, counter_varid, min_counter_value, max_counter_value, strindex, maxMinFlipped)) std::string max_counter_value;
if (!for_condition(tok2, counter_varid, min_counter_value, max_counter_value, maxMinFlipped)) {
// Can't understand the condition. Check that the start value
// is used correctly
const Token *startForScope = tok->next()->link()->next();
if (!for_bailout(startForScope, counter_varid)) {
// Get index variable and stopsize.
bool condition_out_of_bounds = bool(size > 0);
if (MathLib::toLongNumber(counter_init_value) < size)
condition_out_of_bounds = false;
parse_for_body(startForScope, arrayInfo, counter_name, condition_out_of_bounds, counter_varid, counter_init_value, counter_init_value);
}
return; return;
}
// Get index variable and stopsize. // Get index variable and stopsize.
bool condition_out_of_bounds = bool(size > 0); bool condition_out_of_bounds = bool(size > 0);
@ -751,7 +766,7 @@ void CheckBufferOverrun::checkScopeForBody(const Token *tok, const ArrayInfo &ar
return; return;
} }
parse_for_body(tok2->next(), arrayInfo, strindex, condition_out_of_bounds, counter_varid, min_counter_value, max_counter_value); parse_for_body(tok2->next(), arrayInfo, counter_name, condition_out_of_bounds, counter_varid, min_counter_value, max_counter_value);
} }

View File

@ -1724,6 +1724,15 @@ private:
" }\n" " }\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// Ticket #3893 - start value out of bounds
check("void f() {\n"
" int a[10];\n"
" for (int i = 10; somecondition; dosomething) {\n"
" a[i] = 0;\n"
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds: a\n", errout.str());
} }
void array_index_for_neq() { void array_index_for_neq() {