From 22b41ab2fef764ddc1563467f0ff57d229ee8bfd Mon Sep 17 00:00:00 2001 From: Ignacio Etcheverry Date: Thu, 28 Feb 2019 23:12:49 +0100 Subject: [PATCH] Mono: Fail on script instance creation if constructor was not found Previously this would result in NULL dereferencing. Now we fail with an error. --- modules/mono/csharp_script.cpp | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index a7ac7f46c5b..47be3a99595 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -1528,6 +1528,15 @@ MonoObject *CSharpInstance::_internal_new_managed() { CRASH_COND(!gchandle.is_valid()); #endif + // Search the constructor first, to fail with an error if it's not found before allocating anything else. + GDMonoMethod *ctor = script->script_class->get_method(CACHED_STRING_NAME(dotctor), 0); + if (ctor == NULL) { + ERR_PRINTS("Cannot create script instance because the class does not define a default constructor: " + script->get_path()); + + ERR_EXPLAIN("Constructor not found"); + ERR_FAIL_V(NULL); + } + CSharpLanguage::get_singleton()->release_script_gchandle(gchandle); ERR_FAIL_NULL_V(owner, NULL); @@ -1557,7 +1566,6 @@ MonoObject *CSharpInstance::_internal_new_managed() { CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, owner); // Construct - GDMonoMethod *ctor = script->script_class->get_method(CACHED_STRING_NAME(dotctor), 0); ctor->invoke_raw(mono_object, NULL); return mono_object; @@ -1900,13 +1908,21 @@ bool CSharpScript::_update_exports() { MonoObject *tmp_object = mono_object_new(SCRIPTS_DOMAIN, script_class->get_mono_ptr()); if (!tmp_object) { - ERR_PRINT("Failed to create temporary MonoObject"); + ERR_PRINT("Failed to allocate temporary MonoObject"); return false; } uint32_t tmp_pinned_gchandle = MonoGCHandle::new_strong_handle_pinned(tmp_object); // pin it (not sure if needed) GDMonoMethod *ctor = script_class->get_method(CACHED_STRING_NAME(dotctor), 0); + + if (ctor == NULL) { + ERR_PRINTS("Cannot construct temporary MonoObject because the class does not define a default constructor: " + get_path()); + + ERR_EXPLAIN("Constructor not found"); + ERR_FAIL_V(NULL); + } + MonoException *ctor_exc = NULL; ctor->invoke(tmp_object, NULL, &ctor_exc); @@ -2387,6 +2403,18 @@ StringName CSharpScript::get_instance_base_type() const { CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Variant::CallError &r_error) { /* STEP 1, CREATE */ + + // Search the constructor first, to fail with an error if it's not found before allocating anything else. + GDMonoMethod *ctor = script_class->get_method(CACHED_STRING_NAME(dotctor), p_argcount); + if (ctor == NULL) { + if (p_argcount == 0) { + ERR_PRINTS("Cannot create script instance because the class does not define a default constructor: " + get_path()); + } + + ERR_EXPLAIN("Constructor not found"); + ERR_FAIL_V(NULL); + } + Ref ref; if (p_isref) { // Hold it alive. Important if we have to dispose a script instance binding before creating the CSharpInstance. @@ -2453,7 +2481,6 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, instance->owner); // Construct - GDMonoMethod *ctor = script_class->get_method(CACHED_STRING_NAME(dotctor), p_argcount); ctor->invoke(mono_object, p_args); /* STEP 3, PARTY */