[clang] [clang][analyzer] Change modeling of 'fileno' in checkers. (PR #81842)

via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 16 06:29:06 PST 2024


================
@@ -1404,6 +1486,47 @@ void StreamChecker::evalFeofFerror(const FnDescription *Desc,
   }
 }
 
+void StreamChecker::evalFileno(const FnDescription *Desc, const CallEvent &Call,
+                               CheckerContext &C) const {
+  // Fileno should fail only if the passed pointer is invalid.
+  // Some of the preconditions are checked already in preDefault.
+  // Here we can assume that the operation does not fail.
+  // An added failure case causes many unexpected warnings because a file number
+  // becomes -1 that is not expected by the program.
+  // The stream error states are not modified by 'fileno', and not the 'errno'.
+  // (To ensure that errno is not changed, this evalCall is needed to not
+  // invalidate 'errno' like in a default case.)
+  ProgramStateRef State = C.getState();
+  SymbolRef StreamSym = getStreamArg(Desc, Call).getAsSymbol();
+  if (!StreamSym)
+    return;
+
+  const CallExpr *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
+  if (!CE)
+    return;
+
+  const StreamState *SS = State->get<StreamMap>(StreamSym);
+  if (!SS)
+    return;
+
+  assertStreamStateOpened(SS);
+
+  SValBuilder &SVB = C.getSValBuilder();
+  NonLoc RetVal = makeRetVal(C, CE).castAs<NonLoc>();
+  State = State->BindExpr(CE, C.getLocationContext(), RetVal);
+  auto Cond =
+      SVB.evalBinOp(State, BO_GE, RetVal, SVB.makeZeroVal(Call.getResultType()),
----------------
NagyDonat wrote:

It's a nice trick that you're creating the zero in the type of the other side to avoid surprising type conversion.

There's a chance that I can borrow this solution to handle tricky issues in ArrayBoundCheckerV2 :smile: 

https://github.com/llvm/llvm-project/pull/81842


More information about the cfe-commits mailing list