@@ -65,7 +65,10 @@ static const CWE CWE_BUFFER_OVERRUN(788U); // Access of Memory Location After
6565static const ValueFlow::Value *getBufferSizeValue (const Token *tok)
6666{
6767 const std::list<ValueFlow::Value> &tokenValues = tok->values ();
68- const auto it = std::find_if (tokenValues.cbegin (), tokenValues.cend (), std::mem_fn (&ValueFlow::Value::isBufferSizeValue));
68+ auto it = std::find_if (tokenValues.cbegin (), tokenValues.cend (), std::mem_fn (&ValueFlow::Value::isBufferSizeValue));
69+ if (it != tokenValues.cend ())
70+ return &*it;
71+ it = std::find_if (tokenValues.cbegin (), tokenValues.cend (), std::mem_fn (&ValueFlow::Value::isContainerSizeValue));
6972 return it == tokenValues.cend () ? nullptr : &*it;
7073}
7174
@@ -552,7 +555,7 @@ void CheckBufferOverrunImpl::pointerArithmeticError(const Token *tok, const Toke
552555
553556// ---------------------------------------------------------------------------
554557
555- ValueFlow::Value CheckBufferOverrunImpl::getBufferSize (const Token *bufTok) const
558+ ValueFlow::Value CheckBufferOverrunImpl::getBufferSize (const Token *bufTok, const Settings& settings ) const
556559{
557560 if (!bufTok->valueType ())
558561 return ValueFlow::Value (-1 );
@@ -569,9 +572,20 @@ ValueFlow::Value CheckBufferOverrunImpl::getBufferSize(const Token *bufTok) cons
569572 const Variable *var = bufTok->variable ();
570573
571574 if (!var || var->dimensions ().empty ()) {
572- const ValueFlow::Value *value = getBufferSizeValue (bufTok);
573- if (value)
574- return *value;
575+ if (const ValueFlow::Value *value = getBufferSizeValue (bufTok)) {
576+ if (value->isBufferSizeValue ())
577+ return *value;
578+ else if (value->isContainerSizeValue () && bufTok->valueType () && bufTok->valueType ()->container ) {
579+ const ValueType vtElement = ValueType::parseDecl (bufTok->valueType ()->containerTypeToken , settings);
580+ const size_t elementSize = vtElement.getSizeOf (settings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointer);
581+ if (elementSize > 0 ) {
582+ ValueFlow::Value bufSizeVal;
583+ bufSizeVal.valueType = ValueFlow::Value::ValueType::BUFFER_SIZE ;
584+ bufSizeVal.intvalue = value->intvalue * elementSize;
585+ return bufSizeVal;
586+ }
587+ }
588+ }
575589 }
576590
577591 if (!var || var->isPointer () || (astIsContainer (bufTok) && var->getTypeName () != " std::array" ))
@@ -671,7 +685,7 @@ void CheckBufferOverrunImpl::bufferOverflow()
671685 if (argtok->valueType () && argtok->valueType ()->pointer == 0 )
672686 continue ;
673687 // TODO: strcpy(buf+10, "hello");
674- const ValueFlow::Value bufferSize = getBufferSize (argtok);
688+ const ValueFlow::Value bufferSize = getBufferSize (argtok, mSettings );
675689 if (bufferSize.intvalue <= 0 )
676690 continue ;
677691 // buffer size == 1 => do not warn for dynamic memory
@@ -782,7 +796,7 @@ void CheckBufferOverrunImpl::stringNotZeroTerminated()
782796 const Token *sizeToken = args[2 ];
783797 if (!sizeToken->hasKnownIntValue ())
784798 continue ;
785- const ValueFlow::Value &bufferSize = getBufferSize (args[0 ]);
799+ const ValueFlow::Value &bufferSize = getBufferSize (args[0 ], mSettings );
786800 if (bufferSize.intvalue < 0 || sizeToken->getKnownIntValue () < bufferSize.intvalue )
787801 continue ;
788802 if (Token::simpleMatch (args[1 ], " (" ) && Token::simpleMatch (args[1 ]->astOperand1 (), " . c_str" ) && args[1 ]->astOperand1 ()->astOperand1 ()) {
0 commit comments