acidanthera / bugtracker

Acidanthera Bugtracker
383 stars 44 forks source link

UBSan and GCC #2408

Open sasatasas opened 3 months ago

sasatasas commented 3 months ago

UBSan with GCC.11 and Clang.14

If you remove the check that Undefined Behavior Sanitizer can only be compiled with Clang https://github.com/acidanthera/OpenCorePkg/blob/55bed88fa1eca03d8e9cea17307325828b57bfcd/Library/OcGuardLib/Ubsan.h#L32, then you can build UBSan with GCC.

But it has disadvantages:

The GCC runtime is a downstream copy of the Clang/LLVM runtime, and it has a reduced number of checks, since it's behind upstream. GCC developers sync the Clang/LLVM code from time to time.

There are no unsigned-integer-overflow, implicit-unsigned-integer-truncation, implicit-signed-integer-truncation, implicit-integer-sign-change, local-bounds, function, nullability-* (one of the reasons is because there is no _Nonnull support) checks in GCC. In bounds, there is no possibility of a split call array-bounds and local-bounds subgroups, but there is bounds-strict. See https://releases.llvm.org/14.0.0/tools/clang/docs/UndefinedBehaviorSanitizer.html#available-checks for more details about available checks.

pointer-overflow

In theory, there is a pointer overflow check in GCC, but for some reason it works worse than the implementation in Clang (although there is a check for it). UBSan with the CLANGDWARF toolchain catches much more UB compared to GCC. (If you take the tests from the LLVM repository, then LLVM UBSan will pass them, but GCC UBSan will not. If we take the tests from GCC, then both implementations will pass them.)

There is a difference when displaying location data in memory. So, for example, if a pointer to a variable of some structure overflows, UBSan with GCC will output the address where the variable is located, and with UBSan CLANGDWARF will output the field address.

alignment

They work similarly. But if 2 or more UB occur in one place, then UBSan with GCC reported about only one UB. For example, when "member access within misaligned address..." and "load of misaligned address..." occur in one place, only first report is output with GCC, and both with Clang.