diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 6ac61ecbee4..abe52978852 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -784,7 +784,7 @@ Error ProjectSettings::_load_settings_text(const String &p_path) { next_tag.fields.clear(); next_tag.name = String(); - err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, nullptr, true); + err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, nullptr, true, true); if (err == ERR_FILE_EOF) { // If we're loading a project.godot from source code, we can operate some // ProjectSettings conversions if need be. @@ -986,7 +986,7 @@ Error ProjectSettings::_save_settings_text(const String &p_file, const RBMapstore_string(F.property_name_encode() + "=" + vstr + "\n"); } } @@ -1446,6 +1446,7 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF_BASIC("application/config/version", ""); GLOBAL_DEF_INTERNAL(PropertyInfo(Variant::STRING, "application/config/tags"), PackedStringArray()); GLOBAL_DEF_BASIC(PropertyInfo(Variant::STRING, "application/run/main_scene", PROPERTY_HINT_FILE, "*.tscn,*.scn,*.res"), ""); + GLOBAL_DEF_RST("application/run/disable_modified_security_assistance", false); GLOBAL_DEF("application/run/disable_stdout", false); GLOBAL_DEF("application/run/disable_stderr", false); GLOBAL_DEF("application/run/print_header", true); diff --git a/core/io/config_file.compat.inc b/core/io/config_file.compat.inc new file mode 100644 index 00000000000..d4bee527b92 --- /dev/null +++ b/core/io/config_file.compat.inc @@ -0,0 +1,81 @@ +/**************************************************************************/ +/* config_file.compat.inc */ +/**************************************************************************/ +/* This file is part of: */ +/* REDOT ENGINE */ +/* https://redotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2024-present Redot Engine contributors */ +/* (see REDOT_AUTHORS.md) */ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef DISABLE_DEPRECATED + +Error ConfigFile::_save_bind_compat_redot764(const String &p_path) { + return save(p_path, false); +} + +Error ConfigFile::_load_bind_compat_redot764(const String &p_path) { + return load(p_path, false); +} + +Error ConfigFile::_parse_bind_compat_redot764(const String &p_path) { + return parse(p_path, false); +} + +String ConfigFile::_encode_to_text_bind_compat_redot764() const { + return encode_to_text(false); +} + +Error ConfigFile::_load_encrypted_bind_compat_redot764(const String &p_path, const Vector &p_key) { + return load_encrypted(p_path, p_key, false); +} + +Error ConfigFile::_load_encrypted_pass_bind_compat_redot764(const String &p_path, const String &p_pass) { + return load_encrypted_pass(p_path, p_pass, false); +} + +Error ConfigFile::_save_encrypted_bind_compat_redot764(const String &p_path, const Vector &p_key) { + return save_encrypted(p_path, p_key, false); +} + +Error ConfigFile::_save_encrypted_pass_bind_compat_redot764(const String &p_path, const String &p_pass) { + return save_encrypted_pass(p_path, p_pass, false); +} + +void ConfigFile::_bind_compatibility_methods() { + ClassDB::bind_compatibility_method(D_METHOD("save", "path"), &ConfigFile::_save_bind_compat_redot764); + ClassDB::bind_compatibility_method(D_METHOD("load", "path"), &ConfigFile::_load_bind_compat_redot764); + ClassDB::bind_compatibility_method(D_METHOD("parse", "data"), &ConfigFile::_parse_bind_compat_redot764); + + ClassDB::bind_compatibility_method(D_METHOD("encode_to_text"), &ConfigFile::_encode_to_text_bind_compat_redot764); + + ClassDB::bind_compatibility_method(D_METHOD("load_encrypted", "path", "key"), &ConfigFile::_load_encrypted_bind_compat_redot764); + ClassDB::bind_compatibility_method(D_METHOD("load_encrypted_pass", "path", "password"), &ConfigFile::_load_encrypted_pass_bind_compat_redot764); + + ClassDB::bind_compatibility_method(D_METHOD("save_encrypted", "path", "key"), &ConfigFile::_save_encrypted_bind_compat_redot764); + ClassDB::bind_compatibility_method(D_METHOD("save_encrypted_pass", "path", "password"), &ConfigFile::_save_encrypted_pass_bind_compat_redot764); +} + +#endif diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp index 66d86befff2..cc4fc42a12d 100644 --- a/core/io/config_file.cpp +++ b/core/io/config_file.cpp @@ -31,6 +31,7 @@ /**************************************************************************/ #include "config_file.h" +#include "config_file.compat.inc" #include "core/io/file_access_encrypted.h" #include "core/os/keyboard.h" @@ -133,7 +134,7 @@ void ConfigFile::erase_section_key(const String &p_section, const String &p_key) } } -String ConfigFile::encode_to_text() const { +String ConfigFile::encode_to_text(bool p_full_objects) const { StringBuilder sb; bool first = true; for (const KeyValue> &E : values) { @@ -148,14 +149,14 @@ String ConfigFile::encode_to_text() const { for (const KeyValue &F : E.value) { String vstr; - VariantWriter::write_to_string(F.value, vstr); + VariantWriter::write_to_string(F.value, vstr, nullptr, nullptr, true, p_full_objects); sb.append(F.key.property_name_encode() + "=" + vstr + "\n"); } } return sb.as_string(); } -Error ConfigFile::save(const String &p_path) { +Error ConfigFile::save(const String &p_path, bool p_full_objects) { Error err; Ref file = FileAccess::open(p_path, FileAccess::WRITE, &err); @@ -163,10 +164,10 @@ Error ConfigFile::save(const String &p_path) { return err; } - return _internal_save(file); + return _internal_save(file, p_full_objects); } -Error ConfigFile::save_encrypted(const String &p_path, const Vector &p_key) { +Error ConfigFile::save_encrypted(const String &p_path, const Vector &p_key, bool p_full_objects) { Error err; Ref f = FileAccess::open(p_path, FileAccess::WRITE, &err); @@ -180,10 +181,10 @@ Error ConfigFile::save_encrypted(const String &p_path, const Vector &p_ if (err) { return err; } - return _internal_save(fae); + return _internal_save(fae, p_full_objects); } -Error ConfigFile::save_encrypted_pass(const String &p_path, const String &p_pass) { +Error ConfigFile::save_encrypted_pass(const String &p_path, const String &p_pass, bool p_full_objects) { Error err; Ref f = FileAccess::open(p_path, FileAccess::WRITE, &err); @@ -198,10 +199,10 @@ Error ConfigFile::save_encrypted_pass(const String &p_path, const String &p_pass return err; } - return _internal_save(fae); + return _internal_save(fae, p_full_objects); } -Error ConfigFile::_internal_save(Ref file) { +Error ConfigFile::_internal_save(Ref file, bool p_full_objects) { bool first = true; for (const KeyValue> &E : values) { if (first) { @@ -215,7 +216,7 @@ Error ConfigFile::_internal_save(Ref file) { for (const KeyValue &F : E.value) { String vstr; - VariantWriter::write_to_string(F.value, vstr); + VariantWriter::write_to_string(F.value, vstr, nullptr, nullptr, true, p_full_objects); file->store_string(F.key.property_name_encode() + "=" + vstr + "\n"); } } @@ -223,7 +224,7 @@ Error ConfigFile::_internal_save(Ref file) { return OK; } -Error ConfigFile::load(const String &p_path) { +Error ConfigFile::load(const String &p_path, bool p_allow_objects) { Error err; Ref f = FileAccess::open(p_path, FileAccess::READ, &err); @@ -231,10 +232,10 @@ Error ConfigFile::load(const String &p_path) { return err; } - return _internal_load(p_path, f); + return _internal_load(p_path, f, p_allow_objects); } -Error ConfigFile::load_encrypted(const String &p_path, const Vector &p_key) { +Error ConfigFile::load_encrypted(const String &p_path, const Vector &p_key, bool p_allow_objects) { Error err; Ref f = FileAccess::open(p_path, FileAccess::READ, &err); @@ -248,10 +249,10 @@ Error ConfigFile::load_encrypted(const String &p_path, const Vector &p_ if (err) { return err; } - return _internal_load(p_path, fae); + return _internal_load(p_path, fae, p_allow_objects); } -Error ConfigFile::load_encrypted_pass(const String &p_path, const String &p_pass) { +Error ConfigFile::load_encrypted_pass(const String &p_path, const String &p_pass, bool p_allow_objects) { Error err; Ref f = FileAccess::open(p_path, FileAccess::READ, &err); @@ -266,25 +267,25 @@ Error ConfigFile::load_encrypted_pass(const String &p_path, const String &p_pass return err; } - return _internal_load(p_path, fae); + return _internal_load(p_path, fae, p_allow_objects); } -Error ConfigFile::_internal_load(const String &p_path, Ref f) { +Error ConfigFile::_internal_load(const String &p_path, Ref f, bool p_allow_objects) { VariantParser::StreamFile stream; stream.f = f; - Error err = _parse(p_path, &stream); + Error err = _parse(p_path, &stream, p_allow_objects); return err; } -Error ConfigFile::parse(const String &p_data) { +Error ConfigFile::parse(const String &p_data, bool p_allow_objects) { VariantParser::StreamString stream; stream.s = p_data; - return _parse("", &stream); + return _parse("", &stream, p_allow_objects); } -Error ConfigFile::_parse(const String &p_path, VariantParser::Stream *p_stream) { +Error ConfigFile::_parse(const String &p_path, VariantParser::Stream *p_stream, bool p_allow_objects) { String assign; Variant value; VariantParser::Tag next_tag; @@ -295,11 +296,12 @@ Error ConfigFile::_parse(const String &p_path, VariantParser::Stream *p_stream) String section; while (true) { - assign = Variant(); + assign = String(); + value = Variant(); next_tag.fields.clear(); next_tag.name = String(); - Error err = VariantParser::parse_tag_assign_eof(p_stream, lines, error_text, next_tag, assign, value, nullptr, true); + Error err = VariantParser::parse_tag_assign_eof(p_stream, lines, error_text, next_tag, assign, value, nullptr, true, p_allow_objects); if (err == ERR_FILE_EOF) { return OK; } else if (err != OK) { @@ -334,19 +336,19 @@ void ConfigFile::_bind_methods() { ClassDB::bind_method(D_METHOD("erase_section", "section"), &ConfigFile::erase_section); ClassDB::bind_method(D_METHOD("erase_section_key", "section", "key"), &ConfigFile::erase_section_key); - ClassDB::bind_method(D_METHOD("load", "path"), &ConfigFile::load); - ClassDB::bind_method(D_METHOD("parse", "data"), &ConfigFile::parse); - ClassDB::bind_method(D_METHOD("save", "path"), &ConfigFile::save); + ClassDB::bind_method(D_METHOD("load", "path", "allow_objects"), &ConfigFile::load, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("parse", "data", "allow_objects"), &ConfigFile::parse, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("save", "path", "full_objects"), &ConfigFile::save, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("encode_to_text"), &ConfigFile::encode_to_text); + ClassDB::bind_method(D_METHOD("encode_to_text", "full_objects"), &ConfigFile::encode_to_text, DEFVAL(false)); BIND_METHOD_ERR_RETURN_DOC("load", ERR_FILE_CANT_OPEN); - ClassDB::bind_method(D_METHOD("load_encrypted", "path", "key"), &ConfigFile::load_encrypted); - ClassDB::bind_method(D_METHOD("load_encrypted_pass", "path", "password"), &ConfigFile::load_encrypted_pass); + ClassDB::bind_method(D_METHOD("load_encrypted", "path", "key", "allow_objects"), &ConfigFile::load_encrypted, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("load_encrypted_pass", "path", "password", "allow_objects"), &ConfigFile::load_encrypted_pass, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("save_encrypted", "path", "key"), &ConfigFile::save_encrypted); - ClassDB::bind_method(D_METHOD("save_encrypted_pass", "path", "password"), &ConfigFile::save_encrypted_pass); + ClassDB::bind_method(D_METHOD("save_encrypted", "path", "key", "full_objects"), &ConfigFile::save_encrypted, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("save_encrypted_pass", "path", "password", "full_objects"), &ConfigFile::save_encrypted_pass, DEFVAL(false)); ClassDB::bind_method(D_METHOD("clear"), &ConfigFile::clear); } diff --git a/core/io/config_file.h b/core/io/config_file.h index f0f2c3e3813..d49ba50e435 100644 --- a/core/io/config_file.h +++ b/core/io/config_file.h @@ -45,14 +45,30 @@ class ConfigFile : public RefCounted { PackedStringArray _get_sections() const; PackedStringArray _get_section_keys(const String &p_section) const; - Error _internal_load(const String &p_path, Ref f); - Error _internal_save(Ref file); + Error _internal_load(const String &p_path, Ref f, bool p_allow_objects); + Error _internal_save(Ref file, bool p_full_objects); - Error _parse(const String &p_path, VariantParser::Stream *p_stream); + Error _parse(const String &p_path, VariantParser::Stream *p_stream, bool p_allow_objects); protected: static void _bind_methods(); +#ifndef DISABLE_DEPRECATED + Error _save_bind_compat_redot764(const String &p_path); + Error _load_bind_compat_redot764(const String &p_path); + Error _parse_bind_compat_redot764(const String &p_path); + + String _encode_to_text_bind_compat_redot764() const; + + Error _load_encrypted_bind_compat_redot764(const String &p_path, const Vector &p_key); + Error _load_encrypted_pass_bind_compat_redot764(const String &p_path, const String &p_pass); + + Error _save_encrypted_bind_compat_redot764(const String &p_path, const Vector &p_key); + Error _save_encrypted_pass_bind_compat_redot764(const String &p_path, const String &p_pass); + + static void _bind_compatibility_methods(); +#endif + public: void set_value(const String &p_section, const String &p_key, const Variant &p_value); Variant get_value(const String &p_section, const String &p_key, const Variant &p_default = Variant()) const; @@ -66,19 +82,19 @@ class ConfigFile : public RefCounted { void erase_section(const String &p_section); void erase_section_key(const String &p_section, const String &p_key); - Error save(const String &p_path); - Error load(const String &p_path); - Error parse(const String &p_data); + Error save(const String &p_path, bool p_full_objects = false); + Error load(const String &p_path, bool p_allow_objects = false); + Error parse(const String &p_data, bool p_allow_objects = false); - String encode_to_text() const; // used by exporter + String encode_to_text(bool p_full_objects = false) const; void clear(); - Error load_encrypted(const String &p_path, const Vector &p_key); - Error load_encrypted_pass(const String &p_path, const String &p_pass); + Error load_encrypted(const String &p_path, const Vector &p_key, bool p_allow_objects = false); + Error load_encrypted_pass(const String &p_path, const String &p_pass, bool p_allow_objects = false); - Error save_encrypted(const String &p_path, const Vector &p_key); - Error save_encrypted_pass(const String &p_path, const String &p_pass); + Error save_encrypted(const String &p_path, const Vector &p_key, bool p_full_objects = false); + Error save_encrypted_pass(const String &p_path, const String &p_pass, bool p_full_objects = false); }; #endif // CONFIG_FILE_H diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp index 1e481d3aaa7..d4835f13c0a 100644 --- a/core/io/resource_importer.cpp +++ b/core/io/resource_importer.cpp @@ -73,7 +73,7 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy next_tag.fields.clear(); next_tag.name = String(); - err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, nullptr, true); + err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, nullptr, true, true); if (err == ERR_FILE_EOF) { return OK; } else if (err != OK) { @@ -333,7 +333,7 @@ void ResourceFormatImporter::get_internal_resource_path_list(const String &p_pat next_tag.fields.clear(); next_tag.name = String(); - err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, nullptr, true); + err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, nullptr, true, true); if (err == ERR_FILE_EOF) { return; } else if (err != OK) { @@ -548,12 +548,12 @@ void ResourceImporter::_bind_methods() { Error ResourceFormatImporterSaver::set_uid(const String &p_path, ResourceUID::ID p_uid) { Ref cf; cf.instantiate(); - Error err = cf->load(p_path + ".import"); + Error err = cf->load(p_path + ".import", true); if (err != OK) { return err; } cf->set_value("remap", "uid", ResourceUID::get_singleton()->id_to_text(p_uid)); - cf->save(p_path + ".import"); + cf->save(p_path + ".import", true); return OK; } diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index df12a0a3fdc..28826ae2610 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -1220,7 +1220,7 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem next_tag.fields.clear(); next_tag.name = String(); - err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, nullptr, true); + err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, nullptr, true, true); if (err == ERR_FILE_EOF) { break; } else if (err != OK) { diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp index 49119b9303d..9d6e727d861 100644 --- a/core/variant/variant.cpp +++ b/core/variant/variant.cpp @@ -3623,7 +3623,7 @@ void Variant::construct_from_string(const String &p_string, Variant &r_value, Ob String Variant::get_construct_string() const { String vars; - VariantWriter::write_to_string(*this, vars); + VariantWriter::write_to_string(*this, vars, nullptr, nullptr, true, true); return vars; } diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp index fd04d14f2a1..649f8498019 100644 --- a/core/variant/variant_parser.cpp +++ b/core/variant/variant_parser.cpp @@ -32,6 +32,7 @@ #include "variant_parser.h" +#include "core/config/project_settings.h" #include "core/crypto/crypto_core.h" #include "core/input/input_event.h" #include "core/io/resource_loader.h" @@ -674,10 +675,10 @@ Error VariantParser::_parse_byte_array(Stream *p_stream, Vector &r_cons return OK; } -Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser) { +Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser, bool p_allow_objects) { if (token.type == TK_CURLY_BRACKET_OPEN) { Dictionary d; - Error err = _parse_dictionary(d, p_stream, line, r_err_str, p_res_parser); + Error err = _parse_dictionary(d, p_stream, line, r_err_str, p_res_parser, p_allow_objects); if (err) { return err; } @@ -685,7 +686,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, return OK; } else if (token.type == TK_BRACKET_OPEN) { Array a; - Error err = _parse_array(a, p_stream, line, r_err_str, p_res_parser); + Error err = _parse_array(a, p_stream, line, r_err_str, p_res_parser, p_allow_objects); if (err) { return err; } @@ -992,6 +993,11 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, return ERR_PARSE_ERROR; } } else if (id == "Object") { + if (!p_allow_objects) { + r_err_str = R"(Object decoding is prevented because "allow_objects" is false)"; + return ERR_UNAUTHORIZED; + } + get_token(p_stream, token, line, r_err_str); if (token.type != TK_PARENTHESIS_OPEN) { r_err_str = "Expected '('"; @@ -1077,7 +1083,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } Variant v; - err = parse_value(token, v, p_stream, line, r_err_str, p_res_parser); + err = parse_value(token, v, p_stream, line, r_err_str, p_res_parser, p_allow_objects); if (err) { return err; } @@ -1087,6 +1093,11 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } } } else if (id == "Resource" || id == "SubResource" || id == "ExtResource") { + if (!p_allow_objects) { + r_err_str = R"(Object decoding is prevented because "allow_objects" is false)"; + return ERR_UNAUTHORIZED; + } + get_token(p_stream, token, line, r_err_str); if (token.type != TK_PARENTHESIS_OPEN) { r_err_str = "Expected '('"; @@ -1309,8 +1320,13 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, if (builtin_types.has(token.value)) { array.set_typed(builtin_types.get(token.value), StringName(), Variant()); } else if (token.value == "Resource" || token.value == "SubResource" || token.value == "ExtResource") { + if (!p_allow_objects) { + r_err_str = R"(Object decoding is prevented because "allow_objects" is false)"; + return ERR_UNAUTHORIZED; + } + Variant resource; - err = parse_value(token, resource, p_stream, line, r_err_str, p_res_parser); + err = parse_value(token, resource, p_stream, line, r_err_str, p_res_parser, p_allow_objects); if (err) { if (token.value == "Resource" && err == ERR_PARSE_ERROR && r_err_str == "Expected '('" && token.type == TK_BRACKET_CLOSE) { err = OK; @@ -1351,7 +1367,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } Array values; - err = _parse_array(values, p_stream, line, r_err_str, p_res_parser); + err = _parse_array(values, p_stream, line, r_err_str, p_res_parser, p_allow_objects); if (err) { return err; } @@ -1598,7 +1614,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } } -Error VariantParser::_parse_array(Array &array, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser) { +Error VariantParser::_parse_array(Array &array, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser, bool p_allow_objects) { Token token; bool need_comma = false; @@ -1628,7 +1644,7 @@ Error VariantParser::_parse_array(Array &array, Stream *p_stream, int &line, Str } Variant v; - err = parse_value(token, v, p_stream, line, r_err_str, p_res_parser); + err = parse_value(token, v, p_stream, line, r_err_str, p_res_parser, p_allow_objects); if (err) { return err; } @@ -1638,7 +1654,7 @@ Error VariantParser::_parse_array(Array &array, Stream *p_stream, int &line, Str } } -Error VariantParser::_parse_dictionary(Dictionary &object, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser) { +Error VariantParser::_parse_dictionary(Dictionary &object, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser, bool p_allow_objects) { bool at_key = true; Variant key; Token token; @@ -1670,7 +1686,7 @@ Error VariantParser::_parse_dictionary(Dictionary &object, Stream *p_stream, int } } - err = parse_value(token, key, p_stream, line, r_err_str, p_res_parser); + err = parse_value(token, key, p_stream, line, r_err_str, p_res_parser, p_allow_objects); if (err) { return err; @@ -1693,7 +1709,7 @@ Error VariantParser::_parse_dictionary(Dictionary &object, Stream *p_stream, int } Variant v; - err = parse_value(token, v, p_stream, line, r_err_str, p_res_parser); + err = parse_value(token, v, p_stream, line, r_err_str, p_res_parser, p_allow_objects); if (err && err != ERR_FILE_MISSING_DEPENDENCIES) { return err; } @@ -1704,7 +1720,7 @@ Error VariantParser::_parse_dictionary(Dictionary &object, Stream *p_stream, int } } -Error VariantParser::_parse_tag(Token &token, Stream *p_stream, int &line, String &r_err_str, Tag &r_tag, ResourceParser *p_res_parser, bool p_simple_tag) { +Error VariantParser::_parse_tag(Token &token, Stream *p_stream, int &line, String &r_err_str, Tag &r_tag, ResourceParser *p_res_parser, bool p_simple_tag, bool p_allow_objects) { r_tag.fields.clear(); if (token.type != TK_BRACKET_OPEN) { @@ -1816,7 +1832,7 @@ Error VariantParser::_parse_tag(Token &token, Stream *p_stream, int &line, Strin get_token(p_stream, token, line, r_err_str); Variant value; - Error err = parse_value(token, value, p_stream, line, r_err_str, p_res_parser); + Error err = parse_value(token, value, p_stream, line, r_err_str, p_res_parser, p_allow_objects); if (err) { return err; } @@ -1827,7 +1843,7 @@ Error VariantParser::_parse_tag(Token &token, Stream *p_stream, int &line, Strin return OK; } -Error VariantParser::parse_tag(Stream *p_stream, int &line, String &r_err_str, Tag &r_tag, ResourceParser *p_res_parser, bool p_simple_tag) { +Error VariantParser::parse_tag(Stream *p_stream, int &line, String &r_err_str, Tag &r_tag, ResourceParser *p_res_parser, bool p_simple_tag, bool p_allow_objects) { Token token; get_token(p_stream, token, line, r_err_str); @@ -1840,10 +1856,10 @@ Error VariantParser::parse_tag(Stream *p_stream, int &line, String &r_err_str, T return ERR_PARSE_ERROR; } - return _parse_tag(token, p_stream, line, r_err_str, r_tag, p_res_parser, p_simple_tag); + return _parse_tag(token, p_stream, line, r_err_str, r_tag, p_res_parser, p_simple_tag, p_allow_objects); } -Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r_err_str, Tag &r_tag, String &r_assign, Variant &r_value, ResourceParser *p_res_parser, bool p_simple_tag) { +Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r_err_str, Tag &r_tag, String &r_assign, Variant &r_value, ResourceParser *p_res_parser, bool p_simple_tag, bool p_allow_objects) { //assign.. r_assign = ""; String what; @@ -1880,7 +1896,7 @@ Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r //it's a tag! p_stream->saved = '['; //go back one - Error err = parse_tag(p_stream, line, r_err_str, r_tag, p_res_parser, p_simple_tag); + Error err = parse_tag(p_stream, line, r_err_str, r_tag, p_res_parser, p_simple_tag, p_allow_objects); return err; } @@ -1906,7 +1922,7 @@ Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r r_assign = what; Token token; get_token(p_stream, token, line, r_err_str); - Error err = parse_value(token, r_value, p_stream, line, r_err_str, p_res_parser); + Error err = parse_value(token, r_value, p_stream, line, r_err_str, p_res_parser, p_allow_objects); return err; } } else if (c == '\n') { @@ -1915,7 +1931,7 @@ Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r } } -Error VariantParser::parse(Stream *p_stream, Variant &r_ret, String &r_err_str, int &r_err_line, ResourceParser *p_res_parser) { +Error VariantParser::parse(Stream *p_stream, Variant &r_ret, String &r_err_str, int &r_err_line, ResourceParser *p_res_parser, bool p_allow_objects) { Token token; Error err = get_token(p_stream, token, r_err_line, r_err_str); if (err) { @@ -1926,7 +1942,7 @@ Error VariantParser::parse(Stream *p_stream, Variant &r_ret, String &r_err_str, return ERR_FILE_EOF; } - return parse_value(token, r_ret, p_stream, r_err_line, r_err_str, p_res_parser); + return parse_value(token, r_ret, p_stream, r_err_line, r_err_str, p_res_parser, p_allow_objects); } ////////////////////////////////////////////////////////////////////////////////// @@ -1949,7 +1965,10 @@ static String rtos_fix(double p_value) { } } -Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_string_func, void *p_store_string_ud, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud, int p_recursion_count, bool p_compat) { +Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_string_func, void *p_store_string_ud, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud, int p_recursion_count, bool p_compat, bool p_full_objects) { + static bool modified_security_assistance_disabled = GLOBAL_GET("application/run/disable_modified_security_assistance"); + p_full_objects = p_full_objects || modified_security_assistance_disabled; + switch (p_variant.get_type()) { case Variant::NIL: { p_store_string_func(p_store_string_ud, "null"); @@ -2113,10 +2132,16 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } break; case Variant::OBJECT: { + if (!p_full_objects) { + ERR_PRINT(R"(Object encoding skipped because "full_objects" is false.)"); + p_store_string_func(p_store_string_ud, "null"); + break; + } + if (unlikely(p_recursion_count > MAX_RECURSION)) { ERR_PRINT("Max recursion reached"); p_store_string_func(p_store_string_ud, "null"); - return OK; + break; } p_recursion_count++; @@ -2124,7 +2149,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str if (!obj) { p_store_string_func(p_store_string_ud, "null"); - break; // don't save it + break; } Ref res = p_variant; @@ -2169,7 +2194,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } p_store_string_func(p_store_string_ud, "\"" + E.name + "\":"); - write(obj->get(E.name), p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, p_recursion_count, p_compat); + write(obj->get(E.name), p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, p_recursion_count, p_compat, p_full_objects); } } @@ -2258,9 +2283,9 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str p_store_string_func(p_store_string_ud, "{\n"); for (List::Element *E = keys.front(); E; E = E->next()) { - write(E->get(), p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, p_recursion_count, p_compat); + write(E->get(), p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, p_recursion_count, p_compat, p_full_objects); p_store_string_func(p_store_string_ud, ": "); - write(dict[E->get()], p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, p_recursion_count, p_compat); + write(dict[E->get()], p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, p_recursion_count, p_compat, p_full_objects); if (E->next()) { p_store_string_func(p_store_string_ud, ",\n"); } else { @@ -2288,18 +2313,23 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str Ref