[clang] [clang][analyzer] Support `fgetc` in StreamChecker (PR #72627)
Balázs Kéri via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 23 01:46:18 PST 2023
================
@@ -768,26 +772,65 @@ void StreamChecker::evalFputc(const FnDescription *Desc, const CallEvent &Call,
assertStreamStateOpened(OldSS);
+ // `fgetc` returns the read character on success, otherwise returns EOF.
// `fputc` returns the written character on success, otherwise returns EOF.
- // Generate a transition for the success state.
- std::optional<NonLoc> PutVal = Call.getArgSVal(0).getAs<NonLoc>();
- if (!PutVal)
- return;
- ProgramStateRef StateNotFailed =
- State->BindExpr(CE, C.getLocationContext(), *PutVal);
- StateNotFailed =
- StateNotFailed->set<StreamMap>(StreamSym, StreamState::getOpened(Desc));
- C.addTransition(StateNotFailed);
+ // Generate a transition for the success state of fputc.
+ if (!IsRead) {
+ std::optional<NonLoc> PutVal = Call.getArgSVal(0).getAs<NonLoc>();
+ if (!PutVal)
+ return;
+ ProgramStateRef StateNotFailed =
+ State->BindExpr(CE, C.getLocationContext(), *PutVal);
+ StateNotFailed =
+ StateNotFailed->set<StreamMap>(StreamSym, StreamState::getOpened(Desc));
+ C.addTransition(StateNotFailed);
+ }
+ // Generate a transition for the success state of fgetc.
+ // If we know the state to be FEOF at fgetc, do not add a success state.
+ else if (OldSS->ErrorState != ErrorFEof) {
+ NonLoc RetVal = makeRetVal(C, CE).castAs<NonLoc>();
+ ProgramStateRef StateNotFailed =
+ State->BindExpr(CE, C.getLocationContext(), RetVal);
+ SValBuilder &SVB = C.getSValBuilder();
+ // The returned 'unsigned char' of `fgetc` is converted to 'int',
+ // so we need to check if it is in range [0, 255].
+ auto CondLow = SVB.evalBinOp(State, BO_GE, RetVal,
+ SVB.makeZeroVal(C.getASTContext().IntTy),
+ SVB.getConditionType())
+ .getAs<DefinedOrUnknownSVal>();
+ auto CondHigh = SVB.evalBinOp(State, BO_LE, RetVal,
+ SVB.makeIntVal(255, C.getASTContext().IntTy),
+ SVB.getConditionType())
+ .getAs<DefinedOrUnknownSVal>();
----------------
balazske wrote:
Value "255" can be replaced with `SVB.getBasicValueFactory().getMaxValue(C.getASTContext().UnsignedCharTy).getLimitedValue()` (this is probably not always 255). Probably ASTContext can be saved into a variable.
https://github.com/llvm/llvm-project/pull/72627
More information about the cfe-commits
mailing list