These variants make the choice to terminate the process a compile-time
decision rather than a runtime-configurable setting through
`UBSAN_OPTIONS`. As the compiler can treat any code following these
UBSan handler calls as dead code, it allows for significant
optimizations, such as removing redundant UBSan checks and not needing
to worry about saving volatile registers before calling these.
Generation of this kind of instrumentation can be enabled with
`-fsanitize=undefined -fno-sanitize-recover=undefined`. Build system
support will come in a separate PR.
There is no sensible recovery possible from non-void functions that
fail to return a value, or from `__builtin_unreachable()` being reached,
all bets are off once they happened. This is why LLVM's libsanitizer
treats these as always fatal, even if all other UBSan checks are made
recoverable with `-fsanitize-recover`. The codegen already assumes that
these handlers will not return.
Each of these strings would previously rely on StringView's char const*
constructor overload, which would call __builtin_strlen on the string.
Since we now have operator ""sv, we can replace these with much simpler
versions. This opens the door to being able to remove
StringView(char const*).
No functional changes.
This commit moves the length calculations out to be directly on the
StringView users. This is an important step towards the goal of removing
StringView(char const*), as it moves the responsibility of calculating
the size of the string to the user of the StringView (which will prevent
naive uses causing OOB access).
This makes them harder to miss for spammy apps when UBSAN is not deadly.
Don't commit to making the warnln red at the momment, because that would
probably be a nuisance if stderr is not a tty.
This is the same strategy that LLVM's compiler-rt uses to make sure that
each UBSAN error is only reported once, when UBSAN is *not* deadly.
Otherwise, each time we head through a UB codepath, we will log the same
error over and over. That behavior just adds noise to the logs and makes
it nearly impossible to run binaires that have some common code path
with flagged UB in them.
compiler-rt goes the extra step to make sure the "clear" action is
atomic, but we don't really have that many multi-threaded apps gettting
tested with UBSAN yet, so we can add that later.
The first time we want to print a UBSAN violation, the UBSAN runtime
in userspace will get the UBSAN_OPTIONS environment variable to check if
it contains the string "halt_on_error=1". This is clearly not robust to
invalid options or adding more options, but it gets the job done at the
moment. :^)
Take Kernel/UBSanitizer.cpp and make a copy in LibSanitizer.
We can use LibSanitizer to hold other sanitizers as people implement
them :^).
To enable UBSAN for LibC, DynamicLoader, and other low level system
libraries, LibUBSanitizer is built as a serenity_libc, and has a static
version for LibCStatic to use. The approach is the same as that taken in
Note that this means now UBSAN is enabled for code generators, Lagom,
Kernel, and Userspace with -DENABLE_UNDEFINED_SANTIZER=ON. In userspace
however, UBSAN is not deadly (yet).
Co-authored-by: ForLoveOfCats <ForLoveOfCats@vivaldi.net>