Merge pull request #70994 from reduz/prevent-inspector-resource-recursion
Prevent recursion (and hence crash) in inspector resource assignment.
This commit is contained in:
commit
bb08997b87
1 changed files with 81 additions and 1 deletions
|
@ -3847,7 +3847,87 @@ void EditorPropertyResource::_resource_selected(const Ref<Resource> &p_resource,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool _find_recursive_resources(const Variant &v, HashSet<Resource *> &resources_found) {
|
||||||
|
switch (v.get_type()) {
|
||||||
|
case Variant::ARRAY: {
|
||||||
|
Array a = v;
|
||||||
|
for (int i = 0; i < a.size(); i++) {
|
||||||
|
Variant v2 = a[i];
|
||||||
|
if (v2.get_type() != Variant::ARRAY && v2.get_type() != Variant::DICTIONARY && v2.get_type() != Variant::OBJECT) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (_find_recursive_resources(v2, resources_found)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case Variant::DICTIONARY: {
|
||||||
|
Dictionary d = v;
|
||||||
|
List<Variant> keys;
|
||||||
|
d.get_key_list(&keys);
|
||||||
|
for (const Variant &k : keys) {
|
||||||
|
if (k.get_type() == Variant::ARRAY || k.get_type() == Variant::DICTIONARY || k.get_type() == Variant::OBJECT) {
|
||||||
|
if (_find_recursive_resources(k, resources_found)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Variant v2 = d[k];
|
||||||
|
if (v2.get_type() == Variant::ARRAY || v2.get_type() == Variant::DICTIONARY || v2.get_type() == Variant::OBJECT) {
|
||||||
|
if (_find_recursive_resources(v2, resources_found)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case Variant::OBJECT: {
|
||||||
|
Ref<Resource> r = v;
|
||||||
|
|
||||||
|
if (r.is_null()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resources_found.has(r.ptr())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
resources_found.insert(r.ptr());
|
||||||
|
|
||||||
|
List<PropertyInfo> plist;
|
||||||
|
r->get_property_list(&plist);
|
||||||
|
for (const PropertyInfo &pinfo : plist) {
|
||||||
|
if (!(pinfo.usage & PROPERTY_USAGE_STORAGE)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pinfo.type != Variant::ARRAY && pinfo.type != Variant::DICTIONARY && pinfo.type != Variant::OBJECT) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (_find_recursive_resources(r->get(pinfo.name), resources_found)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
default: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void EditorPropertyResource::_resource_changed(const Ref<Resource> &p_resource) {
|
void EditorPropertyResource::_resource_changed(const Ref<Resource> &p_resource) {
|
||||||
|
Resource *r = Object::cast_to<Resource>(get_edited_object());
|
||||||
|
if (r) {
|
||||||
|
// Check for recursive setting of resource
|
||||||
|
HashSet<Resource *> resources_found;
|
||||||
|
resources_found.insert(r);
|
||||||
|
bool found = _find_recursive_resources(p_resource, resources_found);
|
||||||
|
if (found) {
|
||||||
|
EditorNode::get_singleton()->show_warning(TTR("Recursion detected, unable to assign resource to property."));
|
||||||
|
emit_changed(get_edited_property(), Ref<Resource>());
|
||||||
|
update_property();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Make visual script the correct type.
|
// Make visual script the correct type.
|
||||||
Ref<Script> s = p_resource;
|
Ref<Script> s = p_resource;
|
||||||
|
|
||||||
|
@ -3863,7 +3943,7 @@ void EditorPropertyResource::_resource_changed(const Ref<Resource> &p_resource)
|
||||||
// Prevent the creation of invalid ViewportTextures when possible.
|
// Prevent the creation of invalid ViewportTextures when possible.
|
||||||
Ref<ViewportTexture> vpt = p_resource;
|
Ref<ViewportTexture> vpt = p_resource;
|
||||||
if (vpt.is_valid()) {
|
if (vpt.is_valid()) {
|
||||||
Resource *r = Object::cast_to<Resource>(get_edited_object());
|
r = Object::cast_to<Resource>(get_edited_object());
|
||||||
if (r && r->get_path().is_resource_file()) {
|
if (r && r->get_path().is_resource_file()) {
|
||||||
EditorNode::get_singleton()->show_warning(TTR("Can't create a ViewportTexture on resources saved as a file.\nResource needs to belong to a scene."));
|
EditorNode::get_singleton()->show_warning(TTR("Can't create a ViewportTexture on resources saved as a file.\nResource needs to belong to a scene."));
|
||||||
emit_changed(get_edited_property(), Ref<Resource>());
|
emit_changed(get_edited_property(), Ref<Resource>());
|
||||||
|
|
Loading…
Reference in a new issue