mirror of
https://github.com/godotengine/godot.git
synced 2025-10-19 16:03:29 +00:00
Don't use alloca()
in Object::emit_signalp()
to prevent stack overflow
This commit is contained in:
parent
de463e0241
commit
3eed53686b
1 changed files with 17 additions and 5 deletions
|
@ -1212,8 +1212,13 @@ Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int
|
|||
return ERR_CANT_ACQUIRE_RESOURCE; //no emit, signals blocked
|
||||
}
|
||||
|
||||
Callable *slot_callables = nullptr;
|
||||
uint32_t *slot_flags = nullptr;
|
||||
constexpr int MAX_SLOTS_ON_STACK = 5;
|
||||
// Don't default initialize the Callable objects on the stack, just reserve the space - we'll memnew_placement() them later.
|
||||
alignas(Callable) uint8_t slot_callable_stack[sizeof(Callable) * MAX_SLOTS_ON_STACK];
|
||||
uint32_t slot_flags_stack[MAX_SLOTS_ON_STACK];
|
||||
|
||||
Callable *slot_callables = (Callable *)slot_callable_stack;
|
||||
uint32_t *slot_flags = slot_flags_stack;
|
||||
uint32_t slot_count = 0;
|
||||
|
||||
{
|
||||
|
@ -1234,11 +1239,13 @@ Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int
|
|||
// which is needed in certain edge cases; e.g., https://github.com/godotengine/godot/issues/73889.
|
||||
Ref<RefCounted> rc = Ref<RefCounted>(Object::cast_to<RefCounted>(this));
|
||||
|
||||
if (s->slot_map.size() > MAX_SLOTS_ON_STACK) {
|
||||
slot_callables = (Callable *)memalloc(sizeof(Callable) * s->slot_map.size());
|
||||
slot_flags = (uint32_t *)memalloc(sizeof(uint32_t) * s->slot_map.size());
|
||||
}
|
||||
|
||||
// Ensure that disconnecting the signal or even deleting the object
|
||||
// will not affect the signal calling.
|
||||
slot_callables = (Callable *)alloca(sizeof(Callable) * s->slot_map.size());
|
||||
slot_flags = (uint32_t *)alloca(sizeof(uint32_t) * s->slot_map.size());
|
||||
|
||||
for (const KeyValue<Callable, SignalData::Slot> &slot_kv : s->slot_map) {
|
||||
memnew_placement(&slot_callables[slot_count], Callable(slot_kv.value.conn.callable));
|
||||
slot_flags[slot_count] = slot_kv.value.conn.flags;
|
||||
|
@ -1308,6 +1315,11 @@ Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int
|
|||
slot_callables[i].~Callable();
|
||||
}
|
||||
|
||||
if (slot_callables != (Callable *)slot_callable_stack) {
|
||||
memfree(slot_callables);
|
||||
memfree(slot_flags);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue