[core] Fix Callback::create memcpy from function reference

When Callback::create receives a function reference (e.g. void(&)(int)),
&callable gives the address of the function's machine code, not a
pointer variable. The memcpy then reads bytes from executable code
memory instead of copying a function pointer value.

Fix by decaying the callable into a local variable before memcpy,
which converts function references to function pointers stored on
the stack.

No current callers trigger this bug (all pass lambdas), but this
prevents incorrect behavior if bare function names are ever passed.
This commit is contained in:
J. Nick Koston
2026-03-19 18:01:48 -10:00
parent 6e87f8eb4e
commit abd6a4f6a9
+4 -1
View File
@@ -1757,7 +1757,10 @@ template<typename... Ts> struct Callback<void(Ts...)> {
// Safe under C++20 (P0593R6): byte copy into aligned storage implicitly
// creates objects of implicit-lifetime types (trivially copyable qualifies).
Callback cb; // fn and ctx are zero-initialized by default
__builtin_memcpy(&cb.ctx_, &callable, sizeof(DecayF));
// Decay callable to a local variable first. When F is a function reference
// (e.g. void(&)(int)), &callable would point at machine code, not a pointer variable.
DecayF decayed = std::forward<F>(callable);
__builtin_memcpy(&cb.ctx_, &decayed, sizeof(DecayF));
cb.fn_ = [](void *c, Ts... args) {
alignas(DecayF) char buf[sizeof(DecayF)];
__builtin_memcpy(buf, &c, sizeof(DecayF));