Fix clang UBSan trigger in sbo_resource.hpp#275
Conversation
|
Thanks. Can you change the PR so it only changes the affected lines? |
c9e28ff to
0e9f7fe
Compare
|
Sure, done ;-) Is the offset to nullptr needed? |
|
You can't use a |
|
I see, if contstexpr is needed and the function needs to perform that UB operation, I do not see solutions. Do you? Should the alignment check be done in the constexpr function? Can it be enforced to programmer doing something like alignas(std::max_align_t) unsigned char storage[1024];
constexpr auto make_resource()
{
return boost::cobalt::detail::sbo_resource(
storage,
sizeof(storage));
}Constexpr buffer should be already aligned, while runtime behavior can be preserved. |
reinterpret_cast cannot be evaluated during constant evaluation, so the plain cast made align_as_max_ ill-formed as a constexpr function. Guard it with std::is_constant_evaluated() and return early at compile time; no real buffer is ever aligned during constant evaluation. Runtime behaviour is unchanged and UBSan-clean under gcc and clang.
|
Hi @klemens-morgenstern, you're right that reinterpret_cast can't be evaluated during constant evaluation, that's exactly why the bare-cast version is rejected. With -Winvalid-constexpr (an error by default on recent clang) it fails to compile even when the function is never called at compile time: But a constexpr function is only ill-formed when no invocation can be a constant expression. Guarding the cast with std::is_constant_evaluated() and returning early restores that. During constant evaluation the function just returns, and at runtime it does the normal integer-arithmetic alignment: constexpr void align_as_max_()
{
if (std::is_constant_evaluated())
return;
const auto buffer = reinterpret_cast<std::uintptr_t>(buffer_.p);
...
}Skipping alignment at compile time is fine here: no real buffer is ever aligned during constant evaluation. The only ctor that calls align_as_max_() takes a (void*, size) and its sole users construct it at runtime (op::awaitable lives in a coroutine frame, which can't be constexpr; composition gets its resource from handler.get_allocator()); the default ctor used by get_null_sbo_resource() doesn't touch it. Verified compile + run clean, and UBSan + ASan clean, under both gcc 15 and clang 21 in C++20 — covering the misaligned-start (the originally-flagged branch), too-small, and empty-buffer paths. Also confirmed valid constexpr under clang -Werror=invalid-constexpr and g++. |
Running my application with UB sanitizers enabled, catched this line computing the offset from nullptr and then adding buffer + padding to nullptr again:
The UBSan error: