Browse Source

Fix Variant Ref<> assignment.

-Creating from object pointer via funcptr API was missing reference initialization.
-Supersedes https://github.com/godotengine/godot-cpp/pull/662
-Fixes several crashes in GDExtension
reduz 3 years ago
parent
commit
3ad3a43063
3 changed files with 21 additions and 4 deletions
  1. 7 0
      core/variant/variant.cpp
  2. 1 0
      core/variant/variant.h
  3. 13 4
      core/variant/variant_internal.h

+ 7 - 0
core/variant/variant.cpp

@@ -1023,6 +1023,13 @@ bool Variant::is_null() const {
 	}
 }
 
+bool Variant::initialize_ref(Object *p_object) {
+	RefCounted *ref_counted = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_object));
+	if (!ref_counted->init_ref()) {
+		return false;
+	}
+	return true;
+}
 void Variant::reference(const Variant &p_variant) {
 	switch (type) {
 		case NIL:

+ 1 - 0
core/variant/variant.h

@@ -216,6 +216,7 @@ private:
 	} _data alignas(8);
 
 	void reference(const Variant &p_variant);
+	static bool initialize_ref(Object *p_object);
 
 	void _clear_internal();
 

+ 13 - 4
core/variant/variant_internal.h

@@ -111,6 +111,10 @@ public:
 		}
 	}
 
+	_FORCE_INLINE_ static bool initialize_ref(Object *object) {
+		return Variant::initialize_ref(object);
+	}
+
 	// Atomic types.
 	_FORCE_INLINE_ static bool *get_bool(Variant *v) { return &v->_data._bool; }
 	_FORCE_INLINE_ static const bool *get_bool(const Variant *v) { return &v->_data._bool; }
@@ -1430,10 +1434,15 @@ struct VariantTypeConstructor<Object *> {
 	_FORCE_INLINE_ static void variant_from_type(void *p_variant, void *p_value) {
 		Variant *variant = reinterpret_cast<Variant *>(p_variant);
 		VariantInitializer<Object *>::init(variant);
-		Object *value = *(reinterpret_cast<Object **>(p_value));
-		if (value) {
-			VariantInternalAccessor<Object *>::set(variant, value);
-			VariantInternalAccessor<ObjectID>::set(variant, value->get_instance_id());
+		Object *object = *(reinterpret_cast<Object **>(p_value));
+		if (object) {
+			if (object->is_ref_counted()) {
+				if (!VariantInternal::initialize_ref(object)) {
+					return;
+				}
+			}
+			VariantInternalAccessor<Object *>::set(variant, object);
+			VariantInternalAccessor<ObjectID>::set(variant, object->get_instance_id());
 		}
 	}