From c2ab35bdde2ad5dd0e5cb1a9312bf8da26623f79 Mon Sep 17 00:00:00 2001 From: Thakee Nathees Date: Thu, 19 Mar 2020 11:48:46 +0530 Subject: [PATCH] fixed: saving gdscript with cyclic inheritance crash the editor Fix: #9609 --- modules/gdscript/gdscript.cpp | 29 ++++++++++++++++++++++++++--- modules/gdscript/gdscript.h | 2 +- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index cdd5deb7ee1..5f659f70a05 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -376,10 +376,15 @@ void GDScript::_update_exports_values(Map &values, List base_caches; + if (!p_recursive_call) + base_caches.clear(); + base_caches.append(this); + bool changed = false; if (source_changed_cache) { @@ -473,7 +478,22 @@ bool GDScript::_update_exports() { placeholder_fallback_enabled = false; if (base_cache.is_valid() && base_cache->is_valid()) { - if (base_cache->_update_exports()) { + for (int i = 0; i < base_caches.size(); i++) { + if (base_caches[i] == base_cache.ptr()) { + if (r_err) + *r_err = true; + valid = false; // to show error in the editor + base_cache->valid = false; + base_cache->inheriters_cache.clear(); // to prevent future stackoverflows + base_cache.unref(); + base.unref(); + _base = nullptr; + ERR_FAIL_V_MSG(false, "Cyclic inheritance in script class."); + } + } + if (base_cache->_update_exports(r_err, true)) { + if (r_err && *r_err) + return false; changed = true; } } @@ -501,7 +521,10 @@ void GDScript::update_exports() { #ifdef TOOLS_ENABLED - _update_exports(); + bool cyclic_error = false; + _update_exports(&cyclic_error); + if (cyclic_error) + return; Set copy = inheriters_cache; //might get modified diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index 2dbc2252fa0..b7ac2bd0c56 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -135,7 +135,7 @@ class GDScript : public Script { #endif - bool _update_exports(); + bool _update_exports(bool *r_err = nullptr, bool p_recursive_call = false); void _save_orphaned_subclasses(); void _init_rpc_methods_properties();