[all-commits] [llvm/llvm-project] a80418: [analyzer] Improve loads from reinterpret-cast fields

Balazs Benics via All-commits all-commits at lists.llvm.org
Tue Jul 26 03:31:57 PDT 2022


  Branch: refs/heads/main
  Home:   https://github.com/llvm/llvm-project
  Commit: a80418eec001d91f9573456b31704a350e421560
      https://github.com/llvm/llvm-project/commit/a80418eec001d91f9573456b31704a350e421560
  Author: Balazs Benics <benicsbalazs at gmail.com>
  Date:   2022-07-26 (Tue, 26 Jul 2022)

  Changed paths:
    M clang/lib/StaticAnalyzer/Core/RegionStore.cpp
    M clang/test/Analysis/ptr-arith.cpp

  Log Message:
  -----------
  [analyzer] Improve loads from reinterpret-cast fields

Consider this example:

```lang=C++
struct header {
  unsigned a : 1;
  unsigned b : 1;
};
struct parse_t {
  unsigned bits0 : 1;
  unsigned bits2 : 2; // <-- header
  unsigned bits4 : 4;
};
int parse(parse_t *p) {
  unsigned copy = p->bits2;
  clang_analyzer_dump(copy);
  // expected-warning at -1 {{reg_$1<unsigned int SymRegion{reg_$0<struct Bug_55934::parse_t * p>}.bits2>}}

  header *bits = (header *)©
  clang_analyzer_dump(bits->b); // <--- Was UndefinedVal previously.
  // expected-warning at -1 {{derived_$2{reg_$1<unsigned int SymRegion{reg_$0<struct Bug_55934::parse_t * p>}.bits2>,Element{copy,0 S64b,struct Bug_55934::header}.b}}}
  return bits->b; // no-warning: it's not UndefinedVal
}
```

`bits->b` should have the same content as the second bit of `p->bits2`
(assuming that the bitfields are in spelling order).

---

The `Store` has the correct bindings. The problem is with the load of `bits->b`.
It will eventually reach `RegionStoreManager::getBindingForField()` with
`Element{copy,0 S64b,struct header}.b`, which is a `FieldRegion`.
It did not find any direct bindings, so the `getBindingForFieldOrElementCommon()`
gets called. That won't find any bindings, but it sees that the variable
is on the //stack//, thus it must be an uninitialized local variable;
thus it returns `UndefinedVal`.

Instead of doing this, it should have created a //derived symbol//
representing the slice of the region corresponding to the member.
So, if the value of `copy` is `reg1`, then the value of `bits->b` should
be `derived{reg1, elem{copy,0, header}.b}`.

Actually, the `getBindingForElement()` already does exactly this for
reinterpret-casts, so I decided to hoist that and reuse the logic.

Fixes #55934

Reviewed By: martong

Differential Revision: https://reviews.llvm.org/D128535




More information about the All-commits mailing list