Skip to content

Commit 386393c

Browse files
fixup! fixup! fixup! fixup! fixup! fixup! fixup! Fix #958: warn when feof() is used as a while loop condition
1 parent ebde743 commit 386393c

1 file changed

Lines changed: 17 additions & 9 deletions

File tree

lib/checkio.cpp

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -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

501501
void 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

Comments
 (0)