Browse Source

Prevent read-after-free in the queued CallableCustomStaticMethodPointer.

(cherry picked from commit eb81e8b2dcf8bd7e5d1efc933c2d67d357a95546)
bruvzg 1 year ago
parent
commit
d3713220b8
1 changed files with 3 additions and 27 deletions
  1. 3 27
      core/object/callable_method_pointer.h

+ 3 - 27
core/object/callable_method_pointer.h

@@ -81,35 +81,27 @@ template <class T, class... P>
 class CallableCustomMethodPointer : public CallableCustomMethodPointerBase {
 class CallableCustomMethodPointer : public CallableCustomMethodPointerBase {
 	struct Data {
 	struct Data {
 		T *instance;
 		T *instance;
-#ifdef DEBUG_ENABLED
 		uint64_t object_id;
 		uint64_t object_id;
-#endif
 		void (T::*method)(P...);
 		void (T::*method)(P...);
 	} data;
 	} data;
 
 
 public:
 public:
 	virtual ObjectID get_object() const {
 	virtual ObjectID get_object() const {
-#ifdef DEBUG_ENABLED
 		if (ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr) {
 		if (ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr) {
 			return ObjectID();
 			return ObjectID();
 		}
 		}
-#endif
 		return data.instance->get_instance_id();
 		return data.instance->get_instance_id();
 	}
 	}
 
 
 	virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
 	virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
-#ifdef DEBUG_ENABLED
-		ERR_FAIL_COND_MSG(ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr, "Invalid Object id '" + uitos(data.object_id) + "', can't call method.");
-#endif
+		ERR_FAIL_NULL_MSG(ObjectDB::get_instance(ObjectID(data.object_id)), "Invalid Object id '" + uitos(data.object_id) + "', can't call method.");
 		call_with_variant_args(data.instance, data.method, p_arguments, p_argcount, r_call_error);
 		call_with_variant_args(data.instance, data.method, p_arguments, p_argcount, r_call_error);
 	}
 	}
 
 
 	CallableCustomMethodPointer(T *p_instance, void (T::*p_method)(P...)) {
 	CallableCustomMethodPointer(T *p_instance, void (T::*p_method)(P...)) {
 		memset(&data, 0, sizeof(Data)); // Clear beforehand, may have padding bytes.
 		memset(&data, 0, sizeof(Data)); // Clear beforehand, may have padding bytes.
 		data.instance = p_instance;
 		data.instance = p_instance;
-#ifdef DEBUG_ENABLED
 		data.object_id = p_instance->get_instance_id();
 		data.object_id = p_instance->get_instance_id();
-#endif
 		data.method = p_method;
 		data.method = p_method;
 		_setup((uint32_t *)&data, sizeof(Data));
 		_setup((uint32_t *)&data, sizeof(Data));
 	}
 	}
@@ -135,36 +127,28 @@ template <class T, class R, class... P>
 class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase {
 class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase {
 	struct Data {
 	struct Data {
 		T *instance;
 		T *instance;
-#ifdef DEBUG_ENABLED
 		uint64_t object_id;
 		uint64_t object_id;
-#endif
 		R(T::*method)
 		R(T::*method)
 		(P...);
 		(P...);
 	} data;
 	} data;
 
 
 public:
 public:
 	virtual ObjectID get_object() const {
 	virtual ObjectID get_object() const {
-#ifdef DEBUG_ENABLED
 		if (ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr) {
 		if (ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr) {
 			return ObjectID();
 			return ObjectID();
 		}
 		}
-#endif
 		return data.instance->get_instance_id();
 		return data.instance->get_instance_id();
 	}
 	}
 
 
 	virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
 	virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
-#ifdef DEBUG_ENABLED
-		ERR_FAIL_COND_MSG(ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr, "Invalid Object id '" + uitos(data.object_id) + "', can't call method.");
-#endif
+		ERR_FAIL_NULL_MSG(ObjectDB::get_instance(ObjectID(data.object_id)), "Invalid Object id '" + uitos(data.object_id) + "', can't call method.");
 		call_with_variant_args_ret(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
 		call_with_variant_args_ret(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
 	}
 	}
 
 
 	CallableCustomMethodPointerRet(T *p_instance, R (T::*p_method)(P...)) {
 	CallableCustomMethodPointerRet(T *p_instance, R (T::*p_method)(P...)) {
 		memset(&data, 0, sizeof(Data)); // Clear beforehand, may have padding bytes.
 		memset(&data, 0, sizeof(Data)); // Clear beforehand, may have padding bytes.
 		data.instance = p_instance;
 		data.instance = p_instance;
-#ifdef DEBUG_ENABLED
 		data.object_id = p_instance->get_instance_id();
 		data.object_id = p_instance->get_instance_id();
-#endif
 		data.method = p_method;
 		data.method = p_method;
 		_setup((uint32_t *)&data, sizeof(Data));
 		_setup((uint32_t *)&data, sizeof(Data));
 	}
 	}
@@ -190,36 +174,28 @@ template <class T, class R, class... P>
 class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase {
 class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase {
 	struct Data {
 	struct Data {
 		T *instance;
 		T *instance;
-#ifdef DEBUG_ENABLED
 		uint64_t object_id;
 		uint64_t object_id;
-#endif
 		R(T::*method)
 		R(T::*method)
 		(P...) const;
 		(P...) const;
 	} data;
 	} data;
 
 
 public:
 public:
 	virtual ObjectID get_object() const override {
 	virtual ObjectID get_object() const override {
-#ifdef DEBUG_ENABLED
 		if (ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr) {
 		if (ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr) {
 			return ObjectID();
 			return ObjectID();
 		}
 		}
-#endif
 		return data.instance->get_instance_id();
 		return data.instance->get_instance_id();
 	}
 	}
 
 
 	virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override {
 	virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override {
-#ifdef DEBUG_ENABLED
-		ERR_FAIL_COND_MSG(ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr, "Invalid Object id '" + uitos(data.object_id) + "', can't call method.");
-#endif
+		ERR_FAIL_NULL_MSG(ObjectDB::get_instance(ObjectID(data.object_id)), "Invalid Object id '" + uitos(data.object_id) + "', can't call method.");
 		call_with_variant_args_retc(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
 		call_with_variant_args_retc(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
 	}
 	}
 
 
 	CallableCustomMethodPointerRetC(T *p_instance, R (T::*p_method)(P...) const) {
 	CallableCustomMethodPointerRetC(T *p_instance, R (T::*p_method)(P...) const) {
 		memset(&data, 0, sizeof(Data)); // Clear beforehand, may have padding bytes.
 		memset(&data, 0, sizeof(Data)); // Clear beforehand, may have padding bytes.
 		data.instance = p_instance;
 		data.instance = p_instance;
-#ifdef DEBUG_ENABLED
 		data.object_id = p_instance->get_instance_id();
 		data.object_id = p_instance->get_instance_id();
-#endif
 		data.method = p_method;
 		data.method = p_method;
 		_setup((uint32_t *)&data, sizeof(Data));
 		_setup((uint32_t *)&data, sizeof(Data));
 	}
 	}