[clang] [clang][analyzer] Support `fflush` in the StreamChecker (PR #74296)

Alejandro Álvarez Ayllón via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 7 03:02:44 PST 2023


================
@@ -1191,6 +1199,84 @@ void StreamChecker::evalSetFeofFerror(const FnDescription *Desc,
   C.addTransition(State);
 }
 
+void StreamChecker::preFflush(const FnDescription *Desc, const CallEvent &Call,
+                              CheckerContext &C) const {
+  ProgramStateRef State = C.getState();
+  SVal StreamVal = getStreamArg(Desc, Call);
+  std::optional<DefinedSVal> Stream = StreamVal.getAs<DefinedSVal>();
+  SymbolRef StreamSym = StreamVal.getAsSymbol();
+  if (!Stream || !StreamSym)
+    return;
+
+  ProgramStateRef StateNotNull, StateNull;
+  std::tie(StateNotNull, StateNull) =
+      C.getConstraintManager().assumeDual(State, *Stream);
+  if (StateNotNull)
+    if (State = ensureStreamOpened(StreamVal, C, StateNotNull))
+      C.addTransition(State);
+  if (StateNull) {
----------------
alejandro-alvarez-sonarsource wrote:

Due to this transition, these two test cases will behave differently:

```cpp
void test_fflush_2(FILE *F1) {
  fflush(F1);
  // Due to fflush, the analyzer follows a path where F1 is NULL, and another where it isn't.
  // Raises a "Stream pointer might be NULL" on the next line
  if (fwrite("1", 1, 1, F1) == 0)
    return;
  fclose(F1);
}

void test_fflush_3(FILE *F1) {
  // no fflush, the warning does not raise
  if (fwrite("1", 1, 1, F1) == 0)
    return;
  fclose(F1);
}
```

I feel this could be noisy. What do you think about adding the StateNull transition if, and only if, FILE* can be `NULL`?

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


More information about the cfe-commits mailing list