Ver código fonte

fixed: saving gdscript with cyclic inheritance crash the editor

Fix: #9609
(cherry picked from commit c2ab35bdde2ad5dd0e5cb1a9312bf8da26623f79)
Thakee Nathees 5 anos atrás
pai
commit
f3149817ff
2 arquivos alterados com 27 adições e 4 exclusões
  1. 26 3
      modules/gdscript/gdscript.cpp
  2. 1 1
      modules/gdscript/gdscript.h

+ 26 - 3
modules/gdscript/gdscript.cpp

@@ -390,10 +390,15 @@ void GDScript::_update_exports_values(Map<StringName, Variant> &values, List<Pro
 }
 #endif
 
-bool GDScript::_update_exports() {
+bool GDScript::_update_exports(bool *r_err, bool p_recursive_call) {
 
 #ifdef TOOLS_ENABLED
 
+	static Vector<GDScript *> base_caches;
+	if (!p_recursive_call)
+		base_caches.clear();
+	base_caches.push_back(this);
+
 	bool changed = false;
 
 	if (source_changed_cache) {
@@ -487,7 +492,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;
 		}
 	}
@@ -515,7 +535,10 @@ void GDScript::update_exports() {
 
 #ifdef TOOLS_ENABLED
 
-	_update_exports();
+	bool cyclic_error = false;
+	_update_exports(&cyclic_error);
+	if (cyclic_error)
+		return;
 
 	Set<ObjectID> copy = inheriters_cache; //might get modified
 

+ 1 - 1
modules/gdscript/gdscript.h

@@ -132,7 +132,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();