@@ -224,50 +224,55 @@ static bool getDimensionsEtc(const Token * const arrayToken, const Settings *set
224224 return !dimensions->empty ();
225225}
226226
227- static std::vector<const ValueFlow::Value *> getOverrunIndexValues (const Token *tok, const Token *arrayToken, const std::vector<Dimension> &dimensions, const std::vector<const Token *> &indexTokens, MathLib::bigint path)
227+ static ValueFlow::Value makeSizeValue (MathLib::bigint size, MathLib::bigint path)
228+ {
229+ ValueFlow::Value v (size);
230+ v.path = path;
231+ return v;
232+ }
233+
234+ static std::vector<ValueFlow::Value> getOverrunIndexValues (const Token* tok,
235+ const Token* arrayToken,
236+ const std::vector<Dimension>& dimensions,
237+ const std::vector<const Token*>& indexTokens,
238+ MathLib::bigint path)
228239{
229240 const Token *array = arrayToken;
230241 while (Token::Match (array, " .|::" ))
231242 array = array->astOperand2 ();
232243
233- for (int cond = 0 ; cond < 2 ; cond++) {
234- bool equal = false ;
235- bool overflow = false ;
236- bool allKnown = true ;
237- std::vector<const ValueFlow::Value *> indexValues;
238- for (int i = 0 ; i < dimensions.size () && i < indexTokens.size (); ++i) {
239- const ValueFlow::Value *value = indexTokens[i]->getMaxValue (cond == 1 );
240- indexValues.push_back (value);
241- if (!value)
242- continue ;
243- if (value->path != path)
244- continue ;
245- if (!value->isKnown ()) {
246- if (!allKnown)
247- continue ;
248- allKnown = false ;
249- }
250- if (array->variable () && array->variable ()->isArray () && dimensions[i].num == 0 )
251- continue ;
252- if (value->intvalue == dimensions[i].num )
253- equal = true ;
254- else if (value->intvalue > dimensions[i].num )
255- overflow = true ;
256- }
257- if (equal && tok->str () != " [" )
244+ bool isArrayIndex = tok->str () == " [" ;
245+ if (isArrayIndex) {
246+ const Token* parent = tok;
247+ while (Token::simpleMatch (parent, " [" ))
248+ parent = parent->astParent ();
249+ if (!parent || parent->isUnaryOp (" &" ))
250+ isArrayIndex = false ;
251+ }
252+
253+ bool overflow = false ;
254+ std::vector<ValueFlow::Value> indexValues;
255+ for (int i = 0 ; i < dimensions.size () && i < indexTokens.size (); ++i) {
256+ MathLib::bigint size = dimensions[i].num ;
257+ if (!isArrayIndex)
258+ size++;
259+ const bool zeroArray = array->variable () && array->variable ()->isArray () && dimensions[i].num == 0 ;
260+ std::vector<ValueFlow::Value> values = !zeroArray
261+ ? ValueFlow::isOutOfBounds (makeSizeValue (size, path), indexTokens[i])
262+ : std::vector<ValueFlow::Value>{};
263+ if (values.empty ()) {
264+ if (indexTokens[i]->hasKnownIntValue ())
265+ indexValues.push_back (indexTokens[i]->values ().front ());
266+ else
267+ indexValues.push_back (ValueFlow::Value::unknown ());
258268 continue ;
259- if (!overflow && equal) {
260- const Token *parent = tok;
261- while (Token::simpleMatch (parent, " [" ))
262- parent = parent->astParent ();
263- if (!parent || parent->isUnaryOp (" &" ))
264- continue ;
265269 }
266- if ( overflow || equal)
267- return indexValues;
270+ overflow = true ;
271+ indexValues. push_back (values. front ()) ;
268272 }
269-
270- return std::vector<const ValueFlow::Value *>();
273+ if (overflow)
274+ return indexValues;
275+ return {};
271276}
272277
273278void CheckBufferOverrun::arrayIndex ()
@@ -312,45 +317,52 @@ void CheckBufferOverrun::arrayIndex()
312317
313318 // Positive index
314319 if (!mightBeLarger) { // TODO check arrays with dim 1 also
315- const std::vector<const ValueFlow::Value *> &indexValues = getOverrunIndexValues (tok, tok->astOperand1 (), dimensions, indexTokens, path);
320+ const std::vector<ValueFlow::Value>& indexValues =
321+ getOverrunIndexValues (tok, tok->astOperand1 (), dimensions, indexTokens, path);
316322 if (!indexValues.empty ())
317323 arrayIndexError (tok, dimensions, indexValues);
318324 }
319325
320326 // Negative index
321327 bool neg = false ;
322- std::vector<const ValueFlow::Value * > negativeIndexes;
328+ std::vector<ValueFlow::Value> negativeIndexes;
323329 for (const Token * indexToken : indexTokens) {
324330 const ValueFlow::Value *negativeValue = indexToken->getValueLE (-1 , mSettings );
325- negativeIndexes. emplace_back (negativeValue);
326- if ( negativeValue)
331+ if (negativeValue) {
332+ negativeIndexes. emplace_back (* negativeValue);
327333 neg = true ;
334+ } else {
335+ negativeIndexes.emplace_back (ValueFlow::Value::unknown ());
336+ }
328337 }
329338 if (neg) {
330339 negativeIndexError (tok, dimensions, negativeIndexes);
331340 }
332341 }
333342}
334343
335- static std::string stringifyIndexes (const std::string & array, const std::vector<const ValueFlow::Value *> & indexValues)
344+ static std::string stringifyIndexes (const std::string& array, const std::vector<ValueFlow::Value>& indexValues)
336345{
337346 if (indexValues.size () == 1 )
338- return MathLib::toString (indexValues[0 ]-> intvalue );
347+ return MathLib::toString (indexValues[0 ]. intvalue );
339348
340349 std::ostringstream ret;
341350 ret << array;
342- for (const ValueFlow::Value * index : indexValues) {
351+ for (const ValueFlow::Value& index : indexValues) {
343352 ret << " [" ;
344- if (index)
345- ret << index->intvalue ;
346- else
353+ if (index.isNonValue ())
347354 ret << " *" ;
355+ else
356+ ret << index.intvalue ;
348357 ret << " ]" ;
349358 }
350359 return ret.str ();
351360}
352361
353- static std::string arrayIndexMessage (const Token *tok, const std::vector<Dimension> &dimensions, const std::vector<const ValueFlow::Value *> &indexValues, const Token *condition)
362+ static std::string arrayIndexMessage (const Token* tok,
363+ const std::vector<Dimension>& dimensions,
364+ const std::vector<ValueFlow::Value>& indexValues,
365+ const Token* condition)
354366{
355367 auto add_dim = [](const std::string &s, const Dimension &dim) {
356368 return s + " [" + MathLib::toString (dim.num ) + " ]" ;
@@ -367,7 +379,9 @@ static std::string arrayIndexMessage(const Token *tok, const std::vector<Dimensi
367379 return errmsg.str ();
368380}
369381
370- void CheckBufferOverrun::arrayIndexError (const Token *tok, const std::vector<Dimension> &dimensions, const std::vector<const ValueFlow::Value *> &indexes)
382+ void CheckBufferOverrun::arrayIndexError (const Token* tok,
383+ const std::vector<Dimension>& dimensions,
384+ const std::vector<ValueFlow::Value>& indexes)
371385{
372386 if (!tok) {
373387 reportError (tok, Severity::error, " arrayIndexOutOfBounds" , " Array 'arr[16]' accessed at index 16, which is out of bounds." , CWE_BUFFER_OVERRUN, Certainty::normal);
@@ -377,15 +391,13 @@ void CheckBufferOverrun::arrayIndexError(const Token *tok, const std::vector<Dim
377391
378392 const Token *condition = nullptr ;
379393 const ValueFlow::Value *index = nullptr ;
380- for (const ValueFlow::Value *indexValue: indexes) {
381- if (!indexValue)
382- continue ;
383- if (!indexValue->errorSeverity () && !mSettings ->severity .isEnabled (Severity::warning))
394+ for (const ValueFlow::Value& indexValue : indexes) {
395+ if (!indexValue.errorSeverity () && !mSettings ->severity .isEnabled (Severity::warning))
384396 return ;
385- if (indexValue-> condition )
386- condition = indexValue-> condition ;
387- if (!index || !indexValue-> errorPath .empty ())
388- index = indexValue;
397+ if (indexValue. condition )
398+ condition = indexValue. condition ;
399+ if (!index || !indexValue. errorPath .empty ())
400+ index = & indexValue;
389401 }
390402
391403 reportError (getErrorPath (tok, index, " Array index out of bounds" ),
@@ -396,7 +408,9 @@ void CheckBufferOverrun::arrayIndexError(const Token *tok, const std::vector<Dim
396408 index->isInconclusive () ? Certainty::inconclusive : Certainty::normal);
397409}
398410
399- void CheckBufferOverrun::negativeIndexError (const Token *tok, const std::vector<Dimension> &dimensions, const std::vector<const ValueFlow::Value *> &indexes)
411+ void CheckBufferOverrun::negativeIndexError (const Token* tok,
412+ const std::vector<Dimension>& dimensions,
413+ const std::vector<ValueFlow::Value>& indexes)
400414{
401415 if (!tok) {
402416 reportError (tok, Severity::error, " negativeIndex" , " Negative array index" , CWE_BUFFER_UNDERRUN, Certainty::normal);
@@ -405,15 +419,13 @@ void CheckBufferOverrun::negativeIndexError(const Token *tok, const std::vector<
405419
406420 const Token *condition = nullptr ;
407421 const ValueFlow::Value *negativeValue = nullptr ;
408- for (const ValueFlow::Value *indexValue: indexes) {
409- if (!indexValue)
410- continue ;
411- if (!indexValue->errorSeverity () && !mSettings ->severity .isEnabled (Severity::warning))
422+ for (const ValueFlow::Value& indexValue : indexes) {
423+ if (!indexValue.errorSeverity () && !mSettings ->severity .isEnabled (Severity::warning))
412424 return ;
413- if (indexValue-> condition )
414- condition = indexValue-> condition ;
415- if (!negativeValue || !indexValue-> errorPath .empty ())
416- negativeValue = indexValue;
425+ if (indexValue. condition )
426+ condition = indexValue. condition ;
427+ if (!negativeValue || !indexValue. errorPath .empty ())
428+ negativeValue = & indexValue;
417429 }
418430
419431 reportError (getErrorPath (tok, negativeValue, " Negative array index" ),
@@ -464,9 +476,10 @@ void CheckBufferOverrun::pointerArithmetic()
464476 // Positive index
465477 if (!mightBeLarger) { // TODO check arrays with dim 1 also
466478 const std::vector<const Token *> indexTokens{indexToken};
467- const std::vector<const ValueFlow::Value *> &indexValues = getOverrunIndexValues (tok, arrayToken, dimensions, indexTokens, path);
479+ const std::vector<ValueFlow::Value>& indexValues =
480+ getOverrunIndexValues (tok, arrayToken, dimensions, indexTokens, path);
468481 if (!indexValues.empty ())
469- pointerArithmeticError (tok, indexToken, indexValues.front ());
482+ pointerArithmeticError (tok, indexToken, & indexValues.front ());
470483 }
471484
472485 if (const ValueFlow::Value *neg = indexToken->getValueLE (-1 , mSettings ))
0 commit comments