[all-commits] [llvm/llvm-project] 69bc15: [analyzer] Refine invalidation caused by `fread` (...

Balazs Benics via All-commits all-commits at lists.llvm.org
Thu Jun 13 07:13:43 PDT 2024


  Branch: refs/heads/main
  Home:   https://github.com/llvm/llvm-project
  Commit: 69bc159142c6e4ed168e32a6168392d396f891de
      https://github.com/llvm/llvm-project/commit/69bc159142c6e4ed168e32a6168392d396f891de
  Author: Balazs Benics <benicsbalazs at gmail.com>
  Date:   2024-06-13 (Thu, 13 Jun 2024)

  Changed paths:
    M clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
    M clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
    M clang/lib/StaticAnalyzer/Core/MemRegion.cpp
    M clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h
    A clang/test/Analysis/fread.c

  Log Message:
  -----------
  [analyzer] Refine invalidation caused by `fread` (#93408)

This change enables more accurate modeling of the write effects of
`fread`. In particular, instead of invalidating the whole buffer, in a
best-effort basis, we would try to invalidate the actually accesses
elements of the buffer. This preserves the previous value of the buffer
of the unaffected slots. As a result, diagnose more uninitialized buffer
uses for example.

Currently, this refined invalidation only triggers for `fread` if and
only if the `count` parameter and the buffer pointer's index component
are concrete or perfectly-constrained symbols.
Additionally, if the `fread` would read more than 64 elements, the whole
buffer is invalidated as before. This is to have safeguards against
performance issues.

Refer to the comments of the assertions in the following example to see
the changes in the diagnostics:

```c++
void demo() {
  FILE *fp = fopen("/home/test", "rb+");
  if (!fp) return;
  int buffer[10]; // uninitialized
  int read_items = fread(buffer+1, sizeof(int), 5, fp);
  if (5 == read_items) {
    int v1 = buffer[1]; // Unknown value but not garbage.
    clang_analyzer_isTainted(v1); // expected-warning {{YES}} <-- Would be "NO" without this patch.
    clang_analyzer_dump(v1); // expected-warning {{conj_}} <-- Not a "derived" symbol, so it's directly invalidated now.
    int v0 = buffer[0]; // expected-warning {{Assigned value is garbage or undefined}} <-- Had no report here before.
    (void)(v1 + v0);
  } else {
    // If 'fread' had an error.
    int v0 = buffer[0]; // expected-warning {{Assigned value is garbage or undefined}} <-- Had no report here before.
    (void)v0;
  }
  fclose(fp);
}
```

CPP-3247, CPP-3802

Co-authored by Marco Borgeaud (marco-antognini-sonarsource)



To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications


More information about the All-commits mailing list