@@ -652,71 +652,72 @@ void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::str
652652 checkFunctionParameter (*tok, 2 , arrayInfo, callstack);
653653 }
654654
655- // Writing data into array..
656- if ((declarationId > 0 && Token::Match (tok, " strcpy|strcat ( %varid% , %str% )" , declarationId)) ||
657- (declarationId == 0 && Token::Match (tok, (" strcpy|strcat ( " + varnames + " , %str% )" ).c_str ()))) {
658- const std::size_t len = Token::getStrLength (tok->tokAt (varcount + 4 ));
659- if (total_size > 0 && len >= (unsigned int )total_size) {
660- bufferOverrunError (tok, declarationId > 0 ? emptyString : varnames);
661- continue ;
662- }
663- } else if ((declarationId > 0 && Token::Match (tok, " strcpy|strcat ( %varid% , %var% )" , declarationId)) ||
664- (declarationId == 0 && Token::Match (tok, (" strcpy|strcat ( " + varnames + " , %var% )" ).c_str ()))) {
665- const Variable *var = tok->tokAt (4 )->variable ();
666- if (var && var->isArray () && var->dimensions ().size () == 1 ) {
667- const std::size_t len = (std::size_t )var->dimension (0 );
668- if (total_size > 0 && len > (unsigned int )total_size) {
669- if (_settings->inconclusive )
670- possibleBufferOverrunError (tok, tok->strAt (4 ), tok->strAt (2 ), tok->str () == " strcat" );
655+ if (total_size > 0 ) {
656+ // Writing data into array..
657+ if (total_size > 0 && (declarationId > 0 && Token::Match (tok, " strcpy|strcat ( %varid% , %str% )" , declarationId)) ||
658+ (declarationId == 0 && Token::Match (tok, (" strcpy|strcat ( " + varnames + " , %str% )" ).c_str ()))) {
659+ const std::size_t len = Token::getStrLength (tok->tokAt (varcount + 4 ));
660+ if (len >= (unsigned int )total_size) {
661+ bufferOverrunError (tok, declarationId > 0 ? emptyString : varnames);
671662 continue ;
672663 }
664+ } else if ((declarationId > 0 && Token::Match (tok, " strcpy|strcat ( %varid% , %var% )" , declarationId)) ||
665+ (declarationId == 0 && Token::Match (tok, (" strcpy|strcat ( " + varnames + " , %var% )" ).c_str ()))) {
666+ const Variable *var = tok->tokAt (4 )->variable ();
667+ if (var && var->isArray () && var->dimensions ().size () == 1 ) {
668+ const std::size_t len = (std::size_t )var->dimension (0 );
669+ if (len > (unsigned int )total_size) {
670+ if (_settings->inconclusive )
671+ possibleBufferOverrunError (tok, tok->strAt (4 ), tok->strAt (2 ), tok->str () == " strcat" );
672+ continue ;
673+ }
674+ }
673675 }
674- }
675676
676- // Detect few strcat() calls
677- const std::string strcatPattern = declarationId > 0 ? std::string (" strcat ( %varid% , %str% ) ;" ) : (" strcat ( " + varnames + " , %str% ) ;" );
678- if (Token::Match (tok, strcatPattern.c_str (), declarationId)) {
679- std::size_t charactersAppend = 0 ;
680- const Token *tok2 = tok;
677+ // Detect few strcat() calls
678+ const std::string strcatPattern = declarationId > 0 ? std::string (" strcat ( %varid% , %str% ) ;" ) : (" strcat ( " + varnames + " , %str% ) ;" );
679+ if (Token::Match (tok, strcatPattern.c_str (), declarationId)) {
680+ std::size_t charactersAppend = 0 ;
681+ const Token *tok2 = tok;
681682
682- while (Token::Match (tok2, strcatPattern.c_str (), declarationId)) {
683- charactersAppend += Token::getStrLength (tok2->tokAt (4 + varcount));
684- if (charactersAppend >= static_cast <std::size_t >(total_size)) {
685- bufferOverrunError (tok2);
686- break ;
683+ while (Token::Match (tok2, strcatPattern.c_str (), declarationId)) {
684+ charactersAppend += Token::getStrLength (tok2->tokAt (4 + varcount));
685+ if (charactersAppend >= static_cast <std::size_t >(total_size)) {
686+ bufferOverrunError (tok2);
687+ break ;
688+ }
689+ tok2 = tok2->tokAt (7 + varcount);
687690 }
688- tok2 = tok2->tokAt (7 + varcount);
689691 }
690- }
691692
692- // sprintf..
693- // TODO: change total_size to an unsigned value and remove the "&& total_size > 0" check.
694- const std::string sprintfPattern = declarationId > 0 ? std::string (" sprintf ( %varid% , %str% [,)]" ) : (" sprintf ( " + varnames + " , %str% [,)]" );
695- if (Token::Match (tok, sprintfPattern.c_str (), declarationId) && total_size > 0 ) {
696- checkSprintfCall (tok, static_cast <unsigned int >(total_size));
697- }
693+ // sprintf..
694+ const std::string sprintfPattern = declarationId > 0 ? std::string (" sprintf ( %varid% , %str% [,)]" ) : (" sprintf ( " + varnames + " , %str% [,)]" );
695+ if (Token::Match (tok, sprintfPattern.c_str (), declarationId)) {
696+ checkSprintfCall (tok, static_cast <unsigned int >(total_size));
697+ }
698698
699- // snprintf..
700- const std::string snprintfPattern = declarationId > 0 ? std::string (" snprintf ( %varid% , %num% ," ) : (" snprintf ( " + varnames + " , %num% ," );
701- if (Token::Match (tok, snprintfPattern.c_str (), declarationId)) {
702- const MathLib::bigint n = MathLib::toLongNumber (tok->strAt (4 + varcount));
703- if ((n > total_size) && total_size > 0 )
704- outOfBoundsError (tok->tokAt (4 + varcount), " snprintf size" , true , n, total_size);
705- }
699+ // snprintf..
700+ const std::string snprintfPattern = declarationId > 0 ? std::string (" snprintf ( %varid% , %num% ," ) : (" snprintf ( " + varnames + " , %num% ," );
701+ if (Token::Match (tok, snprintfPattern.c_str (), declarationId)) {
702+ const MathLib::bigint n = MathLib::toLongNumber (tok->strAt (4 + varcount));
703+ if (n > total_size )
704+ outOfBoundsError (tok->tokAt (4 + varcount), " snprintf size" , true , n, total_size);
705+ }
706706
707- // Check function call..
708- if (Token::Match (tok, " %var% (" ) && total_size > 0 ) {
709- // No varid => function calls are not handled
710- if (declarationId == 0 )
711- continue ;
707+ // Check function call..
708+ if (Token::Match (tok, " %var% (" )) {
709+ // No varid => function calls are not handled
710+ if (declarationId == 0 )
711+ continue ;
712712
713- const ArrayInfo arrayInfo1 (declarationId, varnames, total_size / size, size);
714- const std::list<const Token *> callstack;
715- checkFunctionCall (tok, arrayInfo1, callstack);
713+ const ArrayInfo arrayInfo1 (declarationId, varnames, total_size / size, size);
714+ const std::list<const Token *> callstack;
715+ checkFunctionCall (tok, arrayInfo1, callstack);
716+ }
716717 }
717718
718719 // undefined behaviour: result of pointer arithmetic is out of bounds
719- else if (declarationId && Token::Match (tok, " = %varid% + %num% ;" , declarationId)) {
720+ if (declarationId && Token::Match (tok, " = %varid% + %num% ;" , declarationId)) {
720721 const MathLib::bigint index = MathLib::toLongNumber (tok->strAt (3 ));
721722 if (isPortabilityEnabled && index > size)
722723 pointerOutOfBoundsError (tok->tokAt (2 ));
@@ -1093,7 +1094,7 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable()
10931094 break ;
10941095 if (tok->str () == " {" )
10951096 tok = tok->next ();
1096- const ArrayInfo arrayInfo (var, _tokenizer, i);
1097+ const ArrayInfo arrayInfo (var, _tokenizer, &_settings-> library , i);
10971098 checkScope (tok, arrayInfo);
10981099 }
10991100 }
@@ -1211,7 +1212,7 @@ void CheckBufferOverrun::checkStructVariable()
12111212 for (var = scope->varlist .begin (); var != scope->varlist .end (); ++var) {
12121213 if (var->isArray ()) {
12131214 // create ArrayInfo from the array variable
1214- ArrayInfo arrayInfo (&*var, _tokenizer);
1215+ ArrayInfo arrayInfo (&*var, _tokenizer, &_settings-> library );
12151216
12161217 // find every function
12171218 const std::size_t functions = symbolDatabase->functionScopes .size ();
@@ -1416,7 +1417,7 @@ void CheckBufferOverrun::bufferOverrun2()
14161417 if (var->dimension (0 ) <= 1 && Token::simpleMatch (var->nameToken ()->linkAt (1 )," ] ; }" ))
14171418 continue ;
14181419
1419- ArrayInfo arrayInfo (var,_tokenizer);
1420+ ArrayInfo arrayInfo (var, _tokenizer, &_settings-> library );
14201421 arrayInfo.varname (varname);
14211422
14221423 valueFlowCheckArrayIndex (tok->next (), arrayInfo);
@@ -1728,7 +1729,7 @@ CheckBufferOverrun::ArrayInfo::ArrayInfo()
17281729{
17291730}
17301731
1731- CheckBufferOverrun::ArrayInfo::ArrayInfo (const Variable *var, const Tokenizer *tokenizer, const unsigned int forcedeclid)
1732+ CheckBufferOverrun::ArrayInfo::ArrayInfo (const Variable *var, const Tokenizer *tokenizer, const Library *library, const unsigned int forcedeclid)
17321733 : _varname(var->name ()), _declarationId((forcedeclid == 0U ) ? var->declarationId() : forcedeclid)
17331734{
17341735 for (std::size_t i = 0 ; i < var->dimensions ().size (); i++)
@@ -1737,8 +1738,14 @@ CheckBufferOverrun::ArrayInfo::ArrayInfo(const Variable *var, const Tokenizer *t
17371738 _element_size = tokenizer->sizeOfType (var->typeEndToken ());
17381739 else if (var->typeStartToken ()->str () == " struct" )
17391740 _element_size = 100 ;
1740- else
1741+ else {
17411742 _element_size = tokenizer->sizeOfType (var->typeEndToken ());
1743+ if (!_element_size) { // try libary
1744+ const Library::PodType* podtype = library->podtype (var->typeEndToken ()->str ());
1745+ if (podtype)
1746+ _element_size = podtype->size ;
1747+ }
1748+ }
17421749}
17431750
17441751/* *
0 commit comments