Browse Source

Prevent circular references to scene being saved, fixes #24384

Juan Linietsky 6 years ago
parent
commit
3ea04c1366

+ 6 - 1
core/io/resource_format_binary.cpp

@@ -1501,7 +1501,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
 
 				if (!resource_set.has(res)) {
 					f->store_32(OBJECT_EMPTY);
-					ERR_EXPLAIN("Resource was not pre cached for the resource section, bug?");
+					ERR_EXPLAIN("Resource was not pre cached for the resource section, most likely due to circular refedence.");
 					ERR_FAIL();
 				}
 
@@ -1650,6 +1650,10 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant
 				return;
 
 			if (!p_main && (!bundle_resources) && res->get_path().length() && res->get_path().find("::") == -1) {
+				if (res->get_path() == path) {
+					ERR_PRINTS("Circular reference to resource being saved found: '" + local_path + "' will be null next time it's loaded.");
+					return;
+				}
 				int idx = external_resources.size();
 				external_resources[res] = idx;
 				return;
@@ -1774,6 +1778,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
 		takeover_paths = false;
 
 	local_path = p_path.get_base_dir();
+	path = ProjectSettings::get_singleton()->localize_path(p_path);
 
 	_find_resources(p_resource, true);
 

+ 1 - 0
core/io/resource_format_binary.h

@@ -114,6 +114,7 @@ public:
 class ResourceFormatSaverBinaryInstance {
 
 	String local_path;
+	String path;
 
 	bool relative_paths;
 	bool bundle_resources;

+ 7 - 1
scene/resources/resource_format_text.cpp

@@ -1361,7 +1361,9 @@ String ResourceFormatSaverTextInstance::_write_resource(const RES &res) {
 		if (internal_resources.has(res)) {
 			return "SubResource( " + itos(internal_resources[res]) + " )";
 		} else if (res->get_path().length() && res->get_path().find("::") == -1) {
-
+			if (res->get_path() == local_path) { //circular reference attempt
+				return "null";
+			}
 			//external resource
 			String path = relative_paths ? local_path.path_to_file(res->get_path()) : res->get_path();
 			return "Resource( \"" + path + "\" )";
@@ -1386,6 +1388,10 @@ void ResourceFormatSaverTextInstance::_find_resources(const Variant &p_variant,
 				return;
 
 			if (!p_main && (!bundle_resources) && res->get_path().length() && res->get_path().find("::") == -1) {
+				if (res->get_path() == local_path) {
+					ERR_PRINTS("Circular reference to resource being saved found: '"+local_path+"' will be null next time it's loaded.");
+					return;
+				}
 				int index = external_resources.size();
 				external_resources[res] = index;
 				return;