From 9fa13da16f0872222c55880fa61a082669c949ab Mon Sep 17 00:00:00 2001 From: rune-scape Date: Thu, 16 May 2024 15:34:28 -0700 Subject: [PATCH] GDScript: fix segfault on invalid script --- modules/gdscript/gdscript.cpp | 48 ++++++++++++++++++++++++++ modules/gdscript/gdscript_compiler.cpp | 6 +++- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index de56dd5ece1..0c58b41fcbf 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -396,6 +396,8 @@ bool GDScript::get_property_default_value(const StringName &p_property, Variant } ScriptInstance *GDScript::instance_create(Object *p_this) { + ERR_FAIL_COND_V_MSG(!valid, nullptr, "Script is invalid!"); + GDScript *top = this; while (top->_base) { top = top->_base; @@ -902,6 +904,11 @@ void GDScript::unload_static() const { } Variant GDScript::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { + if (unlikely(!valid)) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; + return Variant(); + } + GDScript *top = this; while (top) { HashMap::Iterator E = top->member_functions.find(p_method); @@ -924,6 +931,10 @@ bool GDScript::_get(const StringName &p_name, Variant &r_ret) const { return true; } + if (unlikely(!valid)) { + return false; + } + const GDScript *top = this; while (top) { { @@ -980,6 +991,10 @@ bool GDScript::_set(const StringName &p_name, const Variant &p_value) { return true; } + if (unlikely(!valid)) { + return false; + } + GDScript *top = this; while (top) { HashMap::ConstIterator E = top->static_variables_indices.find(p_name); @@ -1014,6 +1029,10 @@ bool GDScript::_set(const StringName &p_name, const Variant &p_value) { void GDScript::_get_property_list(List *p_properties) const { p_properties->push_back(PropertyInfo(Variant::STRING, "script/source", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); + if (unlikely(!valid)) { + return; + } + List classes; const GDScript *top = this; while (top) { @@ -1630,6 +1649,10 @@ GDScript::~GDScript() { ////////////////////////////// bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) { + if (unlikely(!script->valid)) { + return false; + } + { HashMap::Iterator E = script->member_indices.find(p_name); if (E) { @@ -1703,6 +1726,10 @@ bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) { } bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const { + if (unlikely(!script->valid)) { + return false; + } + { HashMap::ConstIterator E = script->member_indices.find(p_name); if (E) { @@ -1823,6 +1850,10 @@ void GDScriptInstance::validate_property(PropertyInfo &p_property) const { } void GDScriptInstance::get_property_list(List *p_properties) const { + if (unlikely(!script->valid)) { + return; + } + // exported members, not done yet! const GDScript *sptr = script.ptr(); @@ -1901,6 +1932,10 @@ void GDScriptInstance::get_property_list(List *p_properties) const } bool GDScriptInstance::property_can_revert(const StringName &p_name) const { + if (unlikely(!script->valid)) { + return false; + } + Variant name = p_name; const Variant *args[1] = { &name }; @@ -1921,6 +1956,10 @@ bool GDScriptInstance::property_can_revert(const StringName &p_name) const { } bool GDScriptInstance::property_get_revert(const StringName &p_name, Variant &r_ret) const { + if (unlikely(!script->valid)) { + return false; + } + Variant name = p_name; const Variant *args[1] = { &name }; @@ -1995,6 +2034,11 @@ void GDScriptInstance::_call_implicit_ready_recursively(GDScript *p_script) { } Variant GDScriptInstance::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { + if (unlikely(!script->valid)) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; + return Variant(); + } + GDScript *sptr = script.ptr(); if (unlikely(p_method == SceneStringName(_ready))) { // Call implicit ready first, including for the super classes recursively. @@ -2012,6 +2056,10 @@ Variant GDScriptInstance::callp(const StringName &p_method, const Variant **p_ar } void GDScriptInstance::notification(int p_notification, bool p_reversed) { + if (unlikely(!script->valid)) { + return; + } + //notification is not virtual, it gets called at ALL levels just like in C. Variant value = p_notification; const Variant *args[1] = { &value }; diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index e62972b949b..eeffc13a100 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -3228,7 +3228,11 @@ Error GDScriptCompiler::compile(const GDScriptParser *p_parser, GDScript *p_scri GDScriptCache::add_static_script(p_script); } - return GDScriptCache::finish_compiling(main_script->path); + err = GDScriptCache::finish_compiling(main_script->path); + if (err) { + main_script->valid = false; + } + return err; } String GDScriptCompiler::get_error() const {