From 84565e4e91d8a1fce75de857c29ff7c70027d6e7 Mon Sep 17 00:00:00 2001 From: Mikael Hermansson Date: Tue, 11 Oct 2022 19:03:12 +0200 Subject: [PATCH] Fix use-after-free at shutdown, sync API files --- binding_generator.py | 15 +++++++++++++++ godot-headers/godot/gdnative_interface.h | 1 + 2 files changed, 16 insertions(+) diff --git a/binding_generator.py b/binding_generator.py index 380033d7cf..d4f3003f74 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -1186,6 +1186,8 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us if is_singleton: result.append(f"\tstatic {class_name} *get_singleton();") result.append("") + result.append(f"\t~{class_name}();") + result.append("") if "methods" in class_api: for method in class_api["methods"]: @@ -1308,6 +1310,8 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us result.append("") if is_singleton: + result.append(f"static bool {class_name}_singleton_destroyed = false;") + result.append("") result.append(f"{class_name} *{class_name}::get_singleton() {{") result.append(f"\tconst StringName __class_name = {class_name}::get_class_static();") result.append( @@ -1319,9 +1323,20 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us result.append( f"\tstatic {class_name} *singleton = reinterpret_cast<{class_name} *>(internal::gdn_interface->object_get_instance_binding(singleton_obj, internal::token, &{class_name}::___binding_callbacks));" ) + result.append(f"\tstatic struct {class_name}_BindingCleanup {{") + result.append(f"\t\t~{class_name}_BindingCleanup() {{") + result.append(f"\t\t\tif (!{class_name}_singleton_destroyed) {{") + result.append("\t\t\t\tinternal::gdn_interface->object_clear_instance_binding(singleton_obj, internal::token);") + result.append("\t\t\t}") + result.append("\t\t}") + result.append("\t} binding_cleanup;") result.append("\treturn singleton;") result.append("}") result.append("") + result.append(f"{class_name}::~{class_name}() {{") + result.append(f"\t{class_name}_singleton_destroyed = true;") + result.append("}") + result.append("") if "methods" in class_api: for method in class_api["methods"]: diff --git a/godot-headers/godot/gdnative_interface.h b/godot-headers/godot/gdnative_interface.h index 50410c4857..49d4e1afd1 100644 --- a/godot-headers/godot/gdnative_interface.h +++ b/godot-headers/godot/gdnative_interface.h @@ -541,6 +541,7 @@ typedef struct { void *(*object_get_instance_binding)(GDNativeObjectPtr p_o, void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks); void (*object_set_instance_binding)(GDNativeObjectPtr p_o, void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks); + void (*object_clear_instance_binding)(GDNativeObjectPtr p_o, void *p_token); void (*object_set_instance)(GDNativeObjectPtr p_o, const GDNativeStringNamePtr p_classname, GDExtensionClassInstancePtr p_instance); /* p_classname should be a registered extension class and should extend the p_o object's class. */