@@ -481,7 +481,7 @@ void CheckIO::invalidScanfError(const Token *tok)
481481 CWE119, Certainty::normal);
482482}
483483
484- static bool findFileReadCall (const Token *start, const Token *end, int varid)
484+ static const Token* findFileReadCall (const Token *start, const Token *end, int varid)
485485{
486486 const Token* found = Token::findmatch (start, " fgets|fgetc|getc|fread|fscanf (" , end);
487487 while (found) {
@@ -491,11 +491,11 @@ static bool findFileReadCall(const Token *start, const Token *end, int varid)
491491 ? args.front ()->varId () == varid
492492 : args.back ()->varId () == varid;
493493 if (match)
494- return true ;
494+ return found ;
495495 }
496496 found = Token::findmatch (found->next (), " fgets|fgetc|getc|fread|fscanf (" , end);
497497 }
498- return false ;
498+ return nullptr ;
499499}
500500
501501void CheckIO::checkWrongfeofUsage ()
@@ -509,15 +509,23 @@ void CheckIO::checkWrongfeofUsage()
509509 if (!Token::simpleMatch (tok, " while ( ! feof (" ))
510510 continue ;
511511
512- // Usage of feof is correct if a read happens before and within the loop
513- const Token *endCond = tok->linkAt (1 );
514- const Token *endBody = endCond->linkAt (1 );
515- const int fpVarId = tok->tokAt (5 )->varId ();
516-
517512 // Bail out if we cannot identify file pointer
513+ const int fpVarId = tok->tokAt (5 )->varId ();
518514 if (fpVarId == 0 )
519515 continue ;
520- if (findFileReadCall (scope->bodyStart , tok, fpVarId) && findFileReadCall (tok, endBody, fpVarId))
516+
517+ // Usage of feof is correct if a read happens before and within the loop.
518+ // However, if we find a control flow statement in between the fileReadCall
519+ // token and the while loop condition, then we bail out.
520+ const Token *endCond = tok->linkAt (1 );
521+ const Token *endBody = endCond->linkAt (1 );
522+
523+ const Token *prevFileReadCallTok = findFileReadCall (scope->bodyStart , tok, fpVarId);
524+ const Token *loopFileReadCallTok = findFileReadCall (tok, endBody, fpVarId);
525+ const Token *prevControlFlowTok = Token::findmatch (prevFileReadCallTok, " return|break|goto|continue|throw" , tok);
526+ const Token *loopControlFlowTok = Token::findmatch (tok, " return|break|goto|continue|throw" , loopFileReadCallTok);
527+
528+ if (prevFileReadCallTok && loopFileReadCallTok && !prevControlFlowTok && !loopControlFlowTok)
521529 continue ;
522530
523531 wrongfeofUsage (getCondTok (tok));
0 commit comments