@@ -248,20 +248,13 @@ void CheckIO::checkFileUsage()
248248
249249 // #1473 Check if fclose is in a while loop condition
250250 if (fileTok && fileTok->isVariable ()) {
251- const Token* tmp = tok->astParent ();
252- const Token* loopTok = nullptr ;
253- while (tmp) {
254- if (Token::simpleMatch (tmp->previous (), " while (" )) {
255- loopTok = tmp->previous ();
256- break ;
257- }
258- tmp = tmp->astParent ();
259- }
260- if (loopTok) {
251+ const Token* loopTok = tok->astTop ()->previous ();
252+
253+ if (loopTok && loopTok->str () == " while" ) {
261254 const Token* bodyEnd = nullptr ;
262255 const Token* bodyStart = nullptr ;
263256
264- if (Token::simpleMatch (loopTok->previous (), " }" ) && Token::simpleMatch ( loopTok->linkAt (- 1 )->previous (), " do " )) { // Handle do-while loops
257+ if (Token::simpleMatch (loopTok->previous (), " }" ) && loopTok->previous ( )->scope ()-> type == ScopeType::eDo) { // Handle do-while loops
265258 bodyEnd = loopTok->previous ();
266259 bodyStart = bodyEnd->link ();
267260 } else {
@@ -271,7 +264,7 @@ void CheckIO::checkFileUsage()
271264
272265 // Do not trigger a warning if the loop always exits or if the file is opened again in the loop.
273266 if (!isReturnScope (bodyEnd, mSettings ->library ) && Token::findmatch (bodyStart, " %var% =" , bodyEnd, fileTok->varId ()) == nullptr )
274- useClosedFileError (tok);
267+ fcloseInLoopConditionError (tok, fileTok-> str () );
275268 }
276269 }
277270 } else if (whitelist.find (tok->str ()) != whitelist.end ()) {
@@ -421,6 +414,15 @@ void CheckIO::useClosedFileError(const Token *tok)
421414 " useClosedFile" , " Used file that is not opened." , CWE910, Certainty::normal);
422415}
423416
417+ void CheckIO::fcloseInLoopConditionError (const Token *tok, const std::string &varname)
418+ {
419+ reportError (tok, Severity::warning,
420+ " fcloseInLoopCondition" ,
421+ " fclose() should not be used as a loop condition.\n "
422+ " fclose() closes '" + varname + " ' each time it is evaluated. On success the loop body might never execute, on failure fclose() might be called again on the already-closed file handle." ,
423+ CWE910, Certainty::normal);
424+ }
425+
424426void CheckIO::seekOnAppendedFileError (const Token *tok)
425427{
426428 reportError (tok, Severity::warning,
@@ -2071,6 +2073,7 @@ void CheckIO::getErrorMessages(ErrorLogger *errorLogger, const Settings *setting
20712073 c.readWriteOnlyFileError (nullptr );
20722074 c.writeReadOnlyFileError (nullptr );
20732075 c.useClosedFileError (nullptr );
2076+ c.fcloseInLoopConditionError (nullptr , " fp" );
20742077 c.seekOnAppendedFileError (nullptr );
20752078 c.incompatibleFileOpenError (nullptr , " tmp" );
20762079 c.invalidScanfError (nullptr );
0 commit comments