Mono: Fail on script instance creation if constructor was not found

Previously this would result in NULL dereferencing. Now we fail with an error.
This commit is contained in:
Ignacio Etcheverry 2019-02-28 23:12:49 +01:00
parent cf6d003df1
commit 22b41ab2fe

View file

@ -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<Reference> 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 */