CheckBufferOverrun: Removed old for-loop handling. This is handled through ValueFlow from now on.
This commit is contained in:
parent
b6a40fceb7
commit
6c8558c112
|
@ -262,315 +262,7 @@ static bool bailoutIfSwitch(const Token *tok, const unsigned int varid)
|
||||||
// No bailout stuff found => return false
|
// No bailout stuff found => return false
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
/**
|
|
||||||
* Parse for loop initialization statement. Look for a counter variable
|
|
||||||
* \param tok [in] first token inside the parentheses
|
|
||||||
* \param varid [out] varid of counter variable
|
|
||||||
* \param varname [out] name of counter variable
|
|
||||||
* \param init_value [out] init value of counter variable
|
|
||||||
* \return success => pointer to the for loop condition. fail => 0. If 0 is returned and varname has been set then there is
|
|
||||||
* a missing varid for the counter variable
|
|
||||||
*/
|
|
||||||
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 (tok->tokAt(2)->isNumber()) {
|
|
||||||
init_value = tok->strAt(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
varid = tok->varId();
|
|
||||||
varname = tok->str();
|
|
||||||
if (varid == 0)
|
|
||||||
return 0; // failed
|
|
||||||
|
|
||||||
tok = tok->tokAt(4);
|
|
||||||
} else if (Token::Match(tok, "%type% %var% = %any% ;")) {
|
|
||||||
if (tok->tokAt(3)->isNumber()) {
|
|
||||||
init_value = tok->strAt(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
varid = tok->next()->varId();
|
|
||||||
varname = tok->next()->str();
|
|
||||||
tok = tok->tokAt(5);
|
|
||||||
} else if (Token::Match(tok, "%type% %type% %var% = %any% ;")) {
|
|
||||||
if (tok->tokAt(4)->isNumber()) {
|
|
||||||
init_value = tok->strAt(4);
|
|
||||||
}
|
|
||||||
|
|
||||||
varid = tok->tokAt(2)->varId();
|
|
||||||
varname = tok->strAt(2);
|
|
||||||
tok = tok->tokAt(6);
|
|
||||||
} else
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!init_value.empty() && (Token::Match(tok, "-- %varid%", varid) || Token::Match(tok, "%varid% --", varid))) {
|
|
||||||
init_value = MathLib::subtract(init_value, "1");
|
|
||||||
}
|
|
||||||
|
|
||||||
return tok;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Parse for condition */
|
|
||||||
static bool for_condition(const Token *tok2, unsigned int varid, std::string &min_value, std::string &max_value, bool &maxMinFlipped)
|
|
||||||
{
|
|
||||||
if (Token::Match(tok2, "%varid% < %num% ;|&&|%oror%", varid) ||
|
|
||||||
Token::Match(tok2, "%varid% != %num% ; ++ %varid%", varid) ||
|
|
||||||
Token::Match(tok2, "%varid% != %num% ; %varid% ++", varid)) {
|
|
||||||
maxMinFlipped = false;
|
|
||||||
const MathLib::bigint value = MathLib::toLongNumber(tok2->strAt(2));
|
|
||||||
max_value = MathLib::toString(value - 1);
|
|
||||||
} else if (Token::Match(tok2, "%varid% <= %num% ;|&&|%oror%", varid)) {
|
|
||||||
maxMinFlipped = false;
|
|
||||||
max_value = tok2->strAt(2);
|
|
||||||
} else if (Token::Match(tok2, "%num% < %varid% ;|&&|%oror%", varid) ||
|
|
||||||
Token::Match(tok2, "%num% != %varid% ; ++ %varid%", varid) ||
|
|
||||||
Token::Match(tok2, "%num% != %varid% ; %varid% ++", varid)) {
|
|
||||||
maxMinFlipped = true;
|
|
||||||
const MathLib::bigint value = MathLib::toLongNumber(tok2->str());
|
|
||||||
max_value = min_value;
|
|
||||||
min_value = MathLib::toString(value + 1);
|
|
||||||
} else if (Token::Match(tok2, "%num% <= %varid% ;|&&|%oror%", varid)) {
|
|
||||||
maxMinFlipped = true;
|
|
||||||
max_value = min_value;
|
|
||||||
min_value = tok2->str();
|
|
||||||
} else if (Token::Match(tok2, "%varid% -- ; )", varid) ||
|
|
||||||
Token::Match(tok2, "-- %varid% ; )", varid)) {
|
|
||||||
maxMinFlipped = true;
|
|
||||||
max_value = min_value;
|
|
||||||
min_value = (tok2->str() == "--") ? "1" : "0";
|
|
||||||
} else {
|
|
||||||
// parse condition
|
|
||||||
while (tok2 && tok2->str() != ";") {
|
|
||||||
if (tok2->str() == "(")
|
|
||||||
tok2 = tok2->link();
|
|
||||||
else if (tok2->str() == ")") // unexpected ")" => break
|
|
||||||
break;
|
|
||||||
if (tok2->str() == "&&" || tok2->str() == "||") {
|
|
||||||
if (for_condition(tok2->next(), varid, min_value, max_value, maxMinFlipped))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
tok2 = tok2->next();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* calculate maximum value of loop variable
|
|
||||||
* @param stepvalue token that contains the step value
|
|
||||||
* @param min_value the minimum value of loop variable
|
|
||||||
* @param max_value maximum value of the loop variable
|
|
||||||
*/
|
|
||||||
static bool for_maxvalue(const Token * const stepvalue, const std::string &min_value, std::string &max_value)
|
|
||||||
{
|
|
||||||
if (!MathLib::isInt(stepvalue->str()))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// We have for example code: "for(i=2;i<22;i+=6)
|
|
||||||
// We can calculate that max value for i is 20, not 21
|
|
||||||
// 21-2 = 19
|
|
||||||
// 19/6 = 3
|
|
||||||
// 6*3+2 = 20
|
|
||||||
const MathLib::bigint num = MathLib::toLongNumber(stepvalue->str());
|
|
||||||
MathLib::bigint max = MathLib::toLongNumber(max_value);
|
|
||||||
const MathLib::bigint min = MathLib::toLongNumber(min_value);
|
|
||||||
max = ((max - min) / num) * num + min;
|
|
||||||
max_value = MathLib::toString(max);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse the third sub-statement in for head
|
|
||||||
* \param tok first token
|
|
||||||
* \param varid variable id of counter
|
|
||||||
* \param min_value min value of counter
|
|
||||||
* \param max_value max value of counter
|
|
||||||
* \param maxMinFlipped counting from max to min
|
|
||||||
*/
|
|
||||||
static bool for3(const Token * const tok,
|
|
||||||
unsigned int varid,
|
|
||||||
std::string &min_value,
|
|
||||||
std::string &max_value,
|
|
||||||
const bool maxMinFlipped)
|
|
||||||
{
|
|
||||||
assert(tok != nullptr);
|
|
||||||
if (Token::Match(tok, "%varid% = %num% + %varid% )", varid)) {
|
|
||||||
if (!for_maxvalue(tok->tokAt(2), min_value, max_value))
|
|
||||||
return false;
|
|
||||||
} else if (Token::Match(tok, "%varid% = %varid% + %num% )", varid)) {
|
|
||||||
if (!for_maxvalue(tok->tokAt(4), min_value, max_value))
|
|
||||||
return false;
|
|
||||||
} else if (Token::Match(tok, "%varid% = %num% - %varid% )", varid)) {
|
|
||||||
if (!for_maxvalue(tok->tokAt(2), min_value, max_value))
|
|
||||||
return false;
|
|
||||||
} else if (Token::Match(tok, "%varid% = %varid% - %num% )", varid)) {
|
|
||||||
if (!for_maxvalue(tok->tokAt(4), min_value, max_value))
|
|
||||||
return false;
|
|
||||||
} else if (Token::Match(tok, "--| %varid% --| )", varid)) {
|
|
||||||
if (!maxMinFlipped && MathLib::toLongNumber(min_value) < MathLib::toLongNumber(max_value)) {
|
|
||||||
// Code relies on the fact that integer will overflow:
|
|
||||||
// for (unsigned int i = 3; i < 5; --i)
|
|
||||||
|
|
||||||
// Set min value in this case to zero.
|
|
||||||
max_value = min_value;
|
|
||||||
min_value = "0";
|
|
||||||
}
|
|
||||||
} else if (! Token::Match(tok, "++| %varid% ++| )", varid)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check is the counter variable increased elsewhere inside the loop or used
|
|
||||||
* for anything else except reading
|
|
||||||
* \param tok1 first token of for-body
|
|
||||||
* \param varid counter variable id
|
|
||||||
* \return bailout needed => true
|
|
||||||
*/
|
|
||||||
static bool for_bailout(const Token * const tok1, unsigned int varid)
|
|
||||||
{
|
|
||||||
for (const Token *loopTok = tok1; loopTok && loopTok != tok1->link(); loopTok = loopTok->next()) {
|
|
||||||
if (loopTok->varId() == varid) {
|
|
||||||
// Counter variable used inside loop
|
|
||||||
if (Token::Match(loopTok->next(), "++|--|=") ||
|
|
||||||
(loopTok->previous()->type() == Token::eIncDecOp)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CheckBufferOverrun::parse_for_body(const Token *tok, const ArrayInfo &arrayInfo, const std::string &strindex, bool condition_out_of_bounds, unsigned int counter_varid, const std::string &min_counter_value, const std::string &max_counter_value)
|
|
||||||
{
|
|
||||||
unsigned int arrayInfoDeclarationId = arrayInfo.declarationId();
|
|
||||||
const std::string pattern = (arrayInfoDeclarationId ? std::string("%varid%") : arrayInfo.varname()) + " [ " + strindex + " ]";
|
|
||||||
|
|
||||||
for (const Token* tok2 = tok; tok2 && tok2 != tok->link(); tok2 = tok2->next()) {
|
|
||||||
// TestBufferOverrun::array_index_for_question
|
|
||||||
if (tok2->str() == "?") {
|
|
||||||
// does condition check counter variable?
|
|
||||||
bool usesCounter = false;
|
|
||||||
const Token *tok3 = tok2->previous();
|
|
||||||
while (Token::Match(tok3, "%comp%|%num%|%var%|)")) {
|
|
||||||
if (tok3->str() == strindex) {
|
|
||||||
usesCounter = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tok3 = tok3->previous();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If strindex is used in the condition then skip the
|
|
||||||
// conditional expressions
|
|
||||||
if (usesCounter) {
|
|
||||||
while (tok2 && !Token::Match(tok2, "[)],;]")) {
|
|
||||||
if (tok2->str() == "(" || tok2->str() == "[")
|
|
||||||
tok2 = tok2->link();
|
|
||||||
tok2 = tok2->next();
|
|
||||||
}
|
|
||||||
if (!tok2)
|
|
||||||
break;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Token::simpleMatch(tok2, "for (") && Token::simpleMatch(tok2->next()->link(), ") {")) {
|
|
||||||
const Token *endpar = tok2->next()->link();
|
|
||||||
const Token *startbody = endpar->next();
|
|
||||||
const Token *endbody = startbody->link();
|
|
||||||
tok2 = endbody;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Token::Match(tok2, "if|switch")) {
|
|
||||||
if (bailoutIfSwitch(tok2, arrayInfoDeclarationId))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (condition_out_of_bounds && Token::Match(tok2, pattern.c_str(), arrayInfoDeclarationId)) {
|
|
||||||
bufferOverrunError(tok2, arrayInfo.varname());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (arrayInfoDeclarationId && tok2->varId() && counter_varid > 0 && !min_counter_value.empty() && !max_counter_value.empty()) {
|
|
||||||
// Is the loop variable used to calculate the array index?
|
|
||||||
// In this scope it is determined if such calculated
|
|
||||||
// array indexes are out of bounds.
|
|
||||||
// Only the minimum and maximum results of the calculation is
|
|
||||||
// determined
|
|
||||||
|
|
||||||
// Minimum calculated array index
|
|
||||||
int min_index = 0;
|
|
||||||
|
|
||||||
// Maximum calculated array index
|
|
||||||
int max_index = 0;
|
|
||||||
|
|
||||||
if (Token::Match(tok2, "%varid% [ %var% +|-|*|/ %num% ]", arrayInfoDeclarationId) &&
|
|
||||||
tok2->tokAt(2)->varId() == counter_varid) {
|
|
||||||
// operator: +-*/
|
|
||||||
const char action = tok2->strAt(3)[0];
|
|
||||||
|
|
||||||
// second operator
|
|
||||||
const std::string &second(tok2->strAt(4));
|
|
||||||
|
|
||||||
//printf("min_index: %s %c %s\n", min_counter_value.c_str(), action, second.c_str());
|
|
||||||
//printf("max_index: %s %c %s\n", max_counter_value.c_str(), action, second.c_str());
|
|
||||||
min_index = std::atoi(MathLib::calculate(min_counter_value, second, action).c_str());
|
|
||||||
max_index = std::atoi(MathLib::calculate(max_counter_value, second, action).c_str());
|
|
||||||
} else if (Token::Match(tok2, "%varid% [ %num% +|-|*|/ %var% ]", arrayInfoDeclarationId) &&
|
|
||||||
tok2->tokAt(4)->varId() == counter_varid) {
|
|
||||||
// operator: +-*/
|
|
||||||
const char action = tok2->strAt(3)[0];
|
|
||||||
|
|
||||||
// first operand
|
|
||||||
const std::string &first(tok2->strAt(2));
|
|
||||||
|
|
||||||
//printf("min_index: %s %c %s\n", first.c_str(), action, min_counter_value.c_str());
|
|
||||||
//printf("max_index: %s %c %s\n", first.c_str(), action, max_counter_value.c_str());
|
|
||||||
|
|
||||||
min_index = std::atoi(MathLib::calculate(first, min_counter_value, action).c_str());
|
|
||||||
max_index = std::atoi(MathLib::calculate(first, max_counter_value, action).c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//printf("min_index = %d, max_index = %d, size = %d\n", min_index, max_index, size);
|
|
||||||
if (min_index < 0 || max_index < 0) {
|
|
||||||
std::vector<MathLib::bigint> indexes;
|
|
||||||
indexes.push_back(std::min(min_index, max_index));
|
|
||||||
arrayIndexOutOfBoundsError(tok2, arrayInfo, indexes);
|
|
||||||
}
|
|
||||||
|
|
||||||
// skip 0 length arrays
|
|
||||||
if (arrayInfo.num(0) == 0)
|
|
||||||
;
|
|
||||||
|
|
||||||
// taking address.
|
|
||||||
else if (tok2->previous()->str() == "&" && max_index == arrayInfo.num(0))
|
|
||||||
;
|
|
||||||
|
|
||||||
else if (arrayInfo.num(0) && (min_index >= arrayInfo.num(0) || max_index >= arrayInfo.num(0))) {
|
|
||||||
std::vector<MathLib::bigint> indexes;
|
|
||||||
indexes.push_back(std::max(min_index, max_index));
|
|
||||||
arrayIndexOutOfBoundsError(tok2, arrayInfo, indexes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CheckBufferOverrun::checkFunctionParameter(const Token &tok, unsigned int par, const ArrayInfo &arrayInfo, const std::list<const Token *>& callstack)
|
void CheckBufferOverrun::checkFunctionParameter(const Token &tok, unsigned int par, const ArrayInfo &arrayInfo, const std::list<const Token *>& callstack)
|
||||||
{
|
{
|
||||||
|
@ -790,132 +482,6 @@ void CheckBufferOverrun::checkFunctionCall(const Token *tok, const ArrayInfo &ar
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CheckBufferOverrun::checkScopeForBody(const Token *tok, const ArrayInfo &arrayInfo, bool &bailout)
|
|
||||||
{
|
|
||||||
bailout = false;
|
|
||||||
|
|
||||||
// Check if there is a break in the body..
|
|
||||||
{
|
|
||||||
const Token *bodyStart = tok->next()->link()->next();
|
|
||||||
const Token *bodyEnd = bodyStart->link();
|
|
||||||
if (Token::findsimplematch(bodyStart, "break ;", bodyEnd))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Token *tok2 = tok->tokAt(2);
|
|
||||||
const MathLib::bigint size = arrayInfo.num(0);
|
|
||||||
|
|
||||||
std::string counter_name;
|
|
||||||
unsigned int counter_varid = 0;
|
|
||||||
std::string counter_init_value;
|
|
||||||
|
|
||||||
tok2 = for_init(tok2, counter_varid, counter_name, counter_init_value);
|
|
||||||
if (tok2 == 0 && !counter_name.empty())
|
|
||||||
_tokenizer->getSymbolDatabase()->debugMessage(tok, "for loop variable \'" + counter_name + "\' has varid 0.");
|
|
||||||
if (tok2 == 0 || counter_varid == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
bool maxMinFlipped = false;
|
|
||||||
std::string min_counter_value = counter_init_value;
|
|
||||||
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 * const 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get index variable and stopsize.
|
|
||||||
bool condition_out_of_bounds = bool(size > 0);
|
|
||||||
if (MathLib::toLongNumber(max_counter_value) < size)
|
|
||||||
condition_out_of_bounds = false;
|
|
||||||
|
|
||||||
// Goto the end of the condition
|
|
||||||
while (tok2 && tok2->str() != ";") {
|
|
||||||
if (tok2->str() == "(")
|
|
||||||
tok2 = tok2->link();
|
|
||||||
else if (tok2->str() == ")") // unexpected ")" => break
|
|
||||||
break;
|
|
||||||
tok2 = tok2->next();
|
|
||||||
}
|
|
||||||
if (!tok2 || tok2->str() != ";")
|
|
||||||
return;
|
|
||||||
const bool hasFor3 = tok2->next()->str() != ")";
|
|
||||||
if (hasFor3 && !for3(tok2->next(), counter_varid, min_counter_value, max_counter_value, maxMinFlipped))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (Token::Match(tok2->next(), "%var% =") && MathLib::toLongNumber(max_counter_value) < size)
|
|
||||||
condition_out_of_bounds = false;
|
|
||||||
|
|
||||||
// Goto the end parentheses of the for-statement: "for (x; y; z)" ..
|
|
||||||
tok2 = tok->next()->link();
|
|
||||||
if (!tok2 || !tok2->tokAt(5)) {
|
|
||||||
bailout = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check is the counter variable increased elsewhere inside the loop or used
|
|
||||||
// for anything else except reading
|
|
||||||
if (for_bailout(tok2->next(), counter_varid)) {
|
|
||||||
bailout = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
parse_for_body(tok2->next(), arrayInfo, counter_name, condition_out_of_bounds, counter_varid, min_counter_value, max_counter_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckBufferOverrun::arrayIndexInForLoop(const Token *tok, const ArrayInfo &arrayInfo)
|
|
||||||
{
|
|
||||||
const MathLib::bigint size = arrayInfo.num(0);
|
|
||||||
const Token *tok3 = tok->tokAt(2);
|
|
||||||
std::string counter_name;
|
|
||||||
unsigned int counter_varid = 0;
|
|
||||||
std::string counter_init_value;
|
|
||||||
|
|
||||||
tok3 = for_init(tok3, counter_varid, counter_name, counter_init_value);
|
|
||||||
if (tok3 == 0 && !counter_name.empty())
|
|
||||||
_tokenizer->getSymbolDatabase()->debugMessage(tok, "for loop variable \'" + counter_name + "\' has varid 0.");
|
|
||||||
if (tok3 == 0 || counter_varid == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
bool maxMinFlipped = false;
|
|
||||||
std::string min_counter_value = counter_init_value;
|
|
||||||
std::string max_counter_value;
|
|
||||||
|
|
||||||
if (!for_condition(tok3, counter_varid, min_counter_value, max_counter_value, maxMinFlipped))
|
|
||||||
return;
|
|
||||||
|
|
||||||
const MathLib::bigint max_value = MathLib::toLongNumber(max_counter_value);
|
|
||||||
|
|
||||||
// Skip condition
|
|
||||||
while (tok3 && tok3->str() != ";")
|
|
||||||
tok3 = tok3->next();
|
|
||||||
|
|
||||||
if (max_value > size && Token::simpleMatch(tok3, "; ) {")) {
|
|
||||||
const Token * const endToken = tok3->linkAt(2);
|
|
||||||
const Token *useToken = nullptr;
|
|
||||||
bool incrementInLoop = false;
|
|
||||||
for (const Token *loopTok = tok3->tokAt(3); loopTok != endToken; loopTok = loopTok->next()) {
|
|
||||||
if (Token::Match(loopTok, "%varid% [ %var% ++| ]", arrayInfo.declarationId()) && loopTok->tokAt(2)->varId() == counter_varid)
|
|
||||||
useToken = loopTok;
|
|
||||||
if (Token::Match(loopTok, "%varid% ++", counter_varid))
|
|
||||||
incrementInLoop = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((useToken != nullptr) && incrementInLoop)
|
|
||||||
bufferOverrunError(useToken, arrayInfo.varname());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::string> &varname, const ArrayInfo &arrayInfo)
|
void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::string> &varname, const ArrayInfo &arrayInfo)
|
||||||
{
|
{
|
||||||
const MathLib::bigint size = arrayInfo.num(0);
|
const MathLib::bigint size = arrayInfo.num(0);
|
||||||
|
@ -1054,18 +620,6 @@ void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::str
|
||||||
checkFunctionParameter(*tok, 2, arrayInfo, callstack);
|
checkFunctionParameter(*tok, 2, arrayInfo, callstack);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop..
|
|
||||||
if (Token::simpleMatch(tok, "for (")) {
|
|
||||||
/*
|
|
||||||
const ArrayInfo arrayInfo1(declarationId, varnames, (unsigned int)size, (unsigned int)total_size);
|
|
||||||
bool bailout = false;
|
|
||||||
checkScopeForBody(tok, arrayInfo1, bailout);
|
|
||||||
if (bailout)
|
|
||||||
break;
|
|
||||||
*/
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writing data into array..
|
// Writing data into array..
|
||||||
if ((declarationId > 0 && Token::Match(tok, "strcpy|strcat ( %varid% , %str% )", declarationId)) ||
|
if ((declarationId > 0 && Token::Match(tok, "strcpy|strcat ( %varid% , %str% )", declarationId)) ||
|
||||||
(declarationId == 0 && Token::Match(tok, ("strcpy|strcat ( " + varnames + " , %str% )").c_str()))) {
|
(declarationId == 0 && Token::Match(tok, ("strcpy|strcat ( " + varnames + " , %str% )").c_str()))) {
|
||||||
|
@ -1276,16 +830,6 @@ void CheckBufferOverrun::checkScope(const Token *tok, const ArrayInfo &arrayInfo
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
else if (Token::Match(tok, "%var% (")) {
|
else if (Token::Match(tok, "%var% (")) {
|
||||||
// Loop..
|
|
||||||
if (Token::simpleMatch(tok, "for (")) {
|
|
||||||
bool bailout = false;
|
|
||||||
arrayIndexInForLoop(tok, arrayInfo);
|
|
||||||
checkScopeForBody(tok, arrayInfo, bailout);
|
|
||||||
if (bailout)
|
|
||||||
break;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check function call..
|
// Check function call..
|
||||||
checkFunctionCall(tok, arrayInfo, std::list<const Token*>());
|
checkFunctionCall(tok, arrayInfo, std::list<const Token*>());
|
||||||
|
|
||||||
|
|
|
@ -180,12 +180,6 @@ public:
|
||||||
/** Check for buffer overruns */
|
/** Check for buffer overruns */
|
||||||
void checkScope(const Token *tok, const std::vector<std::string> &varname, const ArrayInfo &arrayInfo);
|
void checkScope(const Token *tok, const std::vector<std::string> &varname, const ArrayInfo &arrayInfo);
|
||||||
|
|
||||||
/** Check scope helper function - parse for body */
|
|
||||||
void checkScopeForBody(const Token *tok, const ArrayInfo &arrayInfo, bool &bailout);
|
|
||||||
|
|
||||||
/** Helper function used when parsing for-loops */
|
|
||||||
void parse_for_body(const Token *tok2, const ArrayInfo &arrayInfo, const std::string &strindex, bool condition_out_of_bounds, unsigned int counter_varid, const std::string &min_counter_value, const std::string &max_counter_value);
|
|
||||||
|
|
||||||
/** Check readlink or readlinkat() buffer usage */
|
/** Check readlink or readlinkat() buffer usage */
|
||||||
void checkReadlinkBufferUsage(const Token *ftok, const Token *scope_begin, const unsigned int varid, const MathLib::bigint total_size);
|
void checkReadlinkBufferUsage(const Token *ftok, const Token *scope_begin, const unsigned int varid, const MathLib::bigint total_size);
|
||||||
|
|
||||||
|
@ -208,7 +202,6 @@ public:
|
||||||
|
|
||||||
void arrayIndexOutOfBoundsError(const Token *tok, const ArrayInfo &arrayInfo, const std::vector<MathLib::bigint> &index);
|
void arrayIndexOutOfBoundsError(const Token *tok, const ArrayInfo &arrayInfo, const std::vector<MathLib::bigint> &index);
|
||||||
void arrayIndexOutOfBoundsError(const Token *tok, const ArrayInfo &arrayInfo, const std::vector<ValueFlow::Value> &index);
|
void arrayIndexOutOfBoundsError(const Token *tok, const ArrayInfo &arrayInfo, const std::vector<ValueFlow::Value> &index);
|
||||||
void arrayIndexInForLoop(const Token *tok, const ArrayInfo &arrayInfo);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
[samples\bufferAccessOutOfBounds\bad.c:6]: (error) Buffer is accessed out of bounds: a
|
|
||||||
[samples\bufferAccessOutOfBounds\bad.c:6]: (error) Array 'a[2]' accessed at index 2, which is out of bounds.
|
[samples\bufferAccessOutOfBounds\bad.c:6]: (error) Array 'a[2]' accessed at index 2, which is out of bounds.
|
||||||
|
|
|
@ -166,8 +166,7 @@ private:
|
||||||
TEST_CASE(buffer_overrun_21);
|
TEST_CASE(buffer_overrun_21);
|
||||||
TEST_CASE(buffer_overrun_22); // #3124
|
TEST_CASE(buffer_overrun_22); // #3124
|
||||||
TEST_CASE(buffer_overrun_23); // #3153
|
TEST_CASE(buffer_overrun_23); // #3153
|
||||||
TEST_CASE(buffer_overrun_24); // #4106
|
TEST_CASE(buffer_overrun_24); // index variable is changed in for-loop
|
||||||
TEST_CASE(buffer_overrun_25); // #4096
|
|
||||||
TEST_CASE(buffer_overrun_26); // #4432 (segmentation fault)
|
TEST_CASE(buffer_overrun_26); // #4432 (segmentation fault)
|
||||||
TEST_CASE(buffer_overrun_27); // #4444 (segmentation fault)
|
TEST_CASE(buffer_overrun_27); // #4444 (segmentation fault)
|
||||||
TEST_CASE(buffer_overrun_28); // Out of bound char array access
|
TEST_CASE(buffer_overrun_28); // Out of bound char array access
|
||||||
|
@ -402,8 +401,7 @@ private:
|
||||||
" for (i = 0; i < 100; i++)\n"
|
" for (i = 0; i < 100; i++)\n"
|
||||||
" sum += val[i];\n"
|
" sum += val[i];\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:6]: (error) Buffer is accessed out of bounds: val\n"
|
ASSERT_EQUALS("[test.cpp:6]: (error) Array 'val[50]' accessed at index 99, which is out of bounds.\n", errout.str());
|
||||||
"[test.cpp:6]: (error) Array 'val[50]' accessed at index 99, which is out of bounds.\n", errout.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -414,8 +412,7 @@ private:
|
||||||
" for (i = 1; i < 100; i++)\n"
|
" for (i = 1; i < 100; i++)\n"
|
||||||
" sum += val[i];\n"
|
" sum += val[i];\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:6]: (error) Buffer is accessed out of bounds: val\n"
|
ASSERT_EQUALS("[test.cpp:6]: (error) Array 'val[50]' accessed at index 99, which is out of bounds.\n", errout.str());
|
||||||
"[test.cpp:6]: (error) Array 'val[50]' accessed at index 99, which is out of bounds.\n", errout.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -427,8 +424,7 @@ private:
|
||||||
" for (i = a; i < 100; i++)\n"
|
" for (i = a; i < 100; i++)\n"
|
||||||
" sum += val[i];\n"
|
" sum += val[i];\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:6]: (error) Buffer is accessed out of bounds: val\n"
|
ASSERT_EQUALS("[test.cpp:6]: (error) Array 'val[50]' accessed at index 99, which is out of bounds.\n", errout.str());
|
||||||
"[test.cpp:6]: (error) Array 'val[50]' accessed at index 99, which is out of bounds.\n", errout.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -460,8 +456,7 @@ private:
|
||||||
" a[i] = 0;\n"
|
" a[i] = 0;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (error) Buffer is accessed out of bounds: a\n"
|
ASSERT_EQUALS("[test.cpp:3]: (error) Array 'a[10]' accessed at index 49, which is out of bounds.\n", errout.str());
|
||||||
"[test.cpp:3]: (error) Array 'a[10]' accessed at index 49, which is out of bounds.\n", errout.str());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -832,8 +827,7 @@ private:
|
||||||
" for (int i = 0; i < 4; i+=2)\n"
|
" for (int i = 0; i < 4; i+=2)\n"
|
||||||
" a[i] = 0;\n"
|
" a[i] = 0;\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:4]: (error) Buffer is accessed out of bounds: a\n"
|
ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a[2]' accessed at index 2, which is out of bounds.\n", errout.str());
|
||||||
"[test.cpp:4]: (error) Array 'a[2]' accessed at index 2, which is out of bounds.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n" // #4398
|
check("void f() {\n" // #4398
|
||||||
" int a[2];\n"
|
" int a[2];\n"
|
||||||
|
@ -1049,8 +1043,7 @@ private:
|
||||||
" for (int i = 3; 0 <= i; i--)\n"
|
" for (int i = 3; 0 <= i; i--)\n"
|
||||||
" a[i] = i;\n"
|
" a[i] = i;\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:5]: (error) Buffer is accessed out of bounds: a\n"
|
ASSERT_EQUALS("[test.cpp:5]: (error) Array 'a[3]' accessed at index 3, which is out of bounds.\n", errout.str());
|
||||||
"[test.cpp:5]: (error) Array 'a[3]' accessed at index 3, which is out of bounds.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f()\n"
|
check("void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
@ -1068,8 +1061,7 @@ private:
|
||||||
" for (int i = 0; i < 10; i++)\n"
|
" for (int i = 0; i < 10; i++)\n"
|
||||||
" a[i-1] = a[i];\n"
|
" a[i-1] = a[i];\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:5]: (error) Array 'a[10]' accessed at index -1, which is out of bounds.\n"
|
ASSERT_EQUALS("[test.cpp:5]: (error) Array index -1 is out of bounds.\n", errout.str());
|
||||||
"[test.cpp:5]: (error) Array index -1 is out of bounds.\n", errout.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void array_index_28() {
|
void array_index_28() {
|
||||||
|
@ -1533,7 +1525,7 @@ private:
|
||||||
" printf(\"files(%i): %s\n\", 3-i, buffer[3-i]);\n"
|
" printf(\"files(%i): %s\n\", 3-i, buffer[3-i]);\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:4]: (error) Array 'buffer[3]' accessed at index 3, which is out of bounds.\n", errout.str());
|
TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Array 'buffer[3]' accessed at index 3, which is out of bounds.\n", "", errout.str());
|
||||||
|
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" int buffer[9];\n"
|
" int buffer[9];\n"
|
||||||
|
@ -1542,8 +1534,7 @@ private:
|
||||||
" buffer[i] = i;\n"
|
" buffer[i] = i;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:5]: (error) Buffer is accessed out of bounds: buffer\n"
|
ASSERT_EQUALS("[test.cpp:5]: (error) Array 'buffer[9]' accessed at index 9, which is out of bounds.\n", errout.str());
|
||||||
"[test.cpp:5]: (error) Array 'buffer[9]' accessed at index 9, which is out of bounds.\n", errout.str());
|
|
||||||
|
|
||||||
// Correct access limits -> i from 9 to 0
|
// Correct access limits -> i from 9 to 0
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
|
@ -1780,8 +1771,7 @@ private:
|
||||||
" data[i] = 0;\n"
|
" data[i] = 0;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:5]: (error) Buffer is accessed out of bounds: data\n"
|
ASSERT_EQUALS("[test.cpp:5]: (error) Array 'data[8]' accessed at index 10, which is out of bounds.\n", errout.str());
|
||||||
"[test.cpp:5]: (error) Array 'data[8]' accessed at index 10, which is out of bounds.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f()\n"
|
check("void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
@ -1827,8 +1817,7 @@ private:
|
||||||
" data[x] = 0;\n"
|
" data[x] = 0;\n"
|
||||||
" }"
|
" }"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:5]: (error) Buffer is accessed out of bounds: data\n"
|
ASSERT_EQUALS("[test.cpp:5]: (error) Array 'data[2]' accessed at index 9, which is out of bounds.\n", errout.str());
|
||||||
"[test.cpp:5]: (error) Array 'data[2]' accessed at index 9, which is out of bounds.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" char data[2];\n"
|
" char data[2];\n"
|
||||||
|
@ -1837,8 +1826,7 @@ private:
|
||||||
" data[x] = 0;\n"
|
" data[x] = 0;\n"
|
||||||
" }"
|
" }"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:5]: (error) Buffer is accessed out of bounds: data\n"
|
ASSERT_EQUALS("[test.cpp:5]: (error) Array 'data[2]' accessed at index 9, which is out of bounds.\n", errout.str());
|
||||||
"[test.cpp:5]: (error) Array 'data[2]' accessed at index 9, which is out of bounds.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" char data[2];\n"
|
" char data[2];\n"
|
||||||
|
@ -1847,8 +1835,7 @@ private:
|
||||||
" data[x] = 0;\n"
|
" data[x] = 0;\n"
|
||||||
" }"
|
" }"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:5]: (error) Buffer is accessed out of bounds: data\n"
|
ASSERT_EQUALS("[test.cpp:5]: (error) Array 'data[2]' accessed at index 10, which is out of bounds.\n", errout.str());
|
||||||
"[test.cpp:5]: (error) Array 'data[2]' accessed at index 10, which is out of bounds.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" char data[2];\n"
|
" char data[2];\n"
|
||||||
|
@ -1857,8 +1844,7 @@ private:
|
||||||
" data[x] = 0;\n"
|
" data[x] = 0;\n"
|
||||||
" }"
|
" }"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:5]: (error) Buffer is accessed out of bounds: data\n"
|
ASSERT_EQUALS("[test.cpp:5]: (error) Array 'data[2]' accessed at index 10, which is out of bounds.\n", errout.str());
|
||||||
"[test.cpp:5]: (error) Array 'data[2]' accessed at index 10, which is out of bounds.\n", errout.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void array_index_for_continue() {
|
void array_index_for_continue() {
|
||||||
|
@ -1896,8 +1882,7 @@ private:
|
||||||
" a[i] = 0;\n"
|
" a[i] = 0;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:6]: (error) Buffer is accessed out of bounds: a\n"
|
ASSERT_EQUALS("[test.cpp:6]: (error) Array 'a[10]' accessed at index 19, which is out of bounds.\n", errout.str());
|
||||||
"[test.cpp:6]: (error) Array 'a[10]' accessed at index 19, which is out of bounds.\n", errout.str());
|
|
||||||
|
|
||||||
// Ticket #2385 - No false positive
|
// Ticket #2385 - No false positive
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
|
@ -1918,8 +1903,7 @@ private:
|
||||||
" a[i] = 0;\n"
|
" a[i] = 0;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:4]: (error) Buffer is accessed out of bounds: a\n"
|
ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a[10]' accessed at index 10, which is out of bounds.\n", errout.str());
|
||||||
"[test.cpp:4]: (error) Array 'a[10]' accessed at index 10, which is out of bounds.\n", errout.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void array_index_for_neq() {
|
void array_index_for_neq() {
|
||||||
|
@ -1930,8 +1914,7 @@ private:
|
||||||
" a[i] = 0;\n"
|
" a[i] = 0;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:4]: (error) Buffer is accessed out of bounds: a\n"
|
ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a[5]' accessed at index 9, which is out of bounds.\n",
|
||||||
"[test.cpp:4]: (error) Array 'a[5]' accessed at index 9, which is out of bounds.\n",
|
|
||||||
errout.str());
|
errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1951,8 +1934,7 @@ private:
|
||||||
" some_condition ? 0 : a[i-1];\n"
|
" some_condition ? 0 : a[i-1];\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a[10]' accessed at index -1, which is out of bounds.\n"
|
ASSERT_EQUALS("[test.cpp:4]: (error) Array index -1 is out of bounds.\n", errout.str());
|
||||||
"[test.cpp:4]: (error) Array index -1 is out of bounds.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" int a[10];\n"
|
" int a[10];\n"
|
||||||
|
@ -1961,8 +1943,7 @@ private:
|
||||||
" a[i-1] = 0;\n"
|
" a[i-1] = 0;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:5]: (error) Array 'a[10]' accessed at index -1, which is out of bounds.\n"
|
ASSERT_EQUALS("[test.cpp:5]: (error) Array index -1 is out of bounds.\n", errout.str());
|
||||||
"[test.cpp:5]: (error) Array index -1 is out of bounds.\n", errout.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void array_index_for_varid0() { // #4228: No varid for counter variable
|
void array_index_for_varid0() { // #4228: No varid for counter variable
|
||||||
|
@ -2284,8 +2265,7 @@ private:
|
||||||
" for (i = 0; i <= 10; ++i)\n"
|
" for (i = 0; i <= 10; ++i)\n"
|
||||||
" a[i] = 0;\n"
|
" a[i] = 0;\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:7]: (error) Buffer is accessed out of bounds: a\n"
|
ASSERT_EQUALS("[test.cpp:7]: (error) Array 'a[10]' accessed at index 10, which is out of bounds.\n", errout.str());
|
||||||
"[test.cpp:7]: (error) Array 'a[10]' accessed at index 10, which is out of bounds.\n", errout.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2296,8 +2276,7 @@ private:
|
||||||
" for (int i = 0; i < 8; ++i)\n"
|
" for (int i = 0; i < 8; ++i)\n"
|
||||||
" p[i] = 0;\n"
|
" p[i] = 0;\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:5]: (error) Buffer is accessed out of bounds: p\n"
|
ASSERT_EQUALS("[test.cpp:5]: (error) Array 'p[2]' accessed at index 7, which is out of bounds.\n", errout.str());
|
||||||
"[test.cpp:5]: (error) Array 'p[2]' accessed at index 7, which is out of bounds.\n", errout.str());
|
|
||||||
|
|
||||||
// No false positive
|
// No false positive
|
||||||
check("void foo(int x, int y)\n"
|
check("void foo(int x, int y)\n"
|
||||||
|
@ -2627,8 +2606,7 @@ private:
|
||||||
" for (size_t i = 0; i <= 4; i++)\n"
|
" for (size_t i = 0; i <= 4; i++)\n"
|
||||||
" dst[i] = src[i];\n"
|
" dst[i] = src[i];\n"
|
||||||
"} } }\n");
|
"} } }\n");
|
||||||
ASSERT_EQUALS("[test.cpp:6]: (error) Buffer is accessed out of bounds: dst\n"
|
ASSERT_EQUALS("[test.cpp:6]: (error) Array 'dst[4]' accessed at index 4, which is out of bounds.\n", errout.str());
|
||||||
"[test.cpp:6]: (error) Array 'dst[4]' accessed at index 4, which is out of bounds.\n", errout.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void buffer_overrun_22() { // ticket #3124
|
void buffer_overrun_22() { // ticket #3124
|
||||||
|
@ -2672,7 +2650,8 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void buffer_overrun_24() { // ticket #4106
|
void buffer_overrun_24() { // index variable is changed in for-loop
|
||||||
|
// ticket #4106
|
||||||
check("void main() {\n"
|
check("void main() {\n"
|
||||||
" int array[] = {1,2};\n"
|
" int array[] = {1,2};\n"
|
||||||
" int x = 0;\n"
|
" int x = 0;\n"
|
||||||
|
@ -2680,17 +2659,9 @@ private:
|
||||||
" x += array[i];\n"
|
" x += array[i];\n"
|
||||||
" i++; }\n"
|
" i++; }\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:5]: (error) Buffer is accessed out of bounds: array\n", errout.str());
|
TODO_ASSERT_EQUALS("error", "", errout.str());
|
||||||
|
|
||||||
check("void main() {\n"
|
// ticket #4096
|
||||||
" int array[] = {1,2};\n"
|
|
||||||
" for( int i = 0; i<6; ) {\n"
|
|
||||||
" i++; }\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void buffer_overrun_25() { // ticket #4096
|
|
||||||
check("void main() {\n"
|
check("void main() {\n"
|
||||||
" int array[] = {1,2};\n"
|
" int array[] = {1,2};\n"
|
||||||
" int x = 0;\n"
|
" int x = 0;\n"
|
||||||
|
@ -2698,8 +2669,7 @@ private:
|
||||||
" x += array[i++];\n"
|
" x += array[i++];\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}");
|
"}");
|
||||||
|
TODO_ASSERT_EQUALS("error", "", errout.str());
|
||||||
ASSERT_EQUALS("[test.cpp:5]: (error) Buffer is accessed out of bounds: array\n", errout.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void buffer_overrun_26() { // ticket #4432 (segmentation fault)
|
void buffer_overrun_26() { // ticket #4432 (segmentation fault)
|
||||||
|
|
Loading…
Reference in New Issue