mirror of
https://github.com/esphome/esphome.git
synced 2026-09-22 04:28:43 +00:00
[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:
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user