diff --git a/src/native/corehost/comhost/clsidmap.cpp b/src/native/corehost/comhost/clsidmap.cpp index af18abd8b2db92..218516c8da2569 100644 --- a/src/native/corehost/comhost/clsidmap.cpp +++ b/src/native/corehost/comhost/clsidmap.cpp @@ -100,7 +100,7 @@ namespace throw HResultException{ E_UNEXPECTED }; // This should never happen in Windows 7+ json_parser_t json; - if (!json.parse_raw_data(reinterpret_cast(data), size, _X(""))) + if (!json.parse_fully_trusted_raw_data(reinterpret_cast(data), size, _X(""))) { trace::error(_X("Embedded .clsidmap is invalid.\n %s"), json.get_error_message().c_str()); throw HResultException{ StatusCode::InvalidConfigFile }; @@ -178,7 +178,7 @@ namespace return {}; json_parser_t json; - if (!json.parse_file(map_file_name)) + if (!json.parse_fully_trusted_file(map_file_name)) { trace::error(_X("File .clsidmap [%s] is invalid.\n %s"), map_file_name.c_str(), json.get_error_message().c_str()); throw HResultException{ StatusCode::InvalidConfigFile }; diff --git a/src/native/corehost/fxr/sdk_resolver.cpp b/src/native/corehost/fxr/sdk_resolver.cpp index d3063a3db3d5a7..d1bab0d4a5bb2f 100644 --- a/src/native/corehost/fxr/sdk_resolver.cpp +++ b/src/native/corehost/fxr/sdk_resolver.cpp @@ -337,7 +337,7 @@ sdk_resolver::global_file_info sdk_resolver::parse_global_file(const pal::string // After we're done parsing `global_file_path`, none of its contents will be referenced // from the data private to json_parser_t; it's safe to declare it on the stack. json_parser_t json; - if (!json.parse_file(global_file_path)) + if (!json.parse_fully_trusted_file(global_file_path)) { ret.error_message = json.get_error_message(); ret.state = global_file_info::state::invalid_json; diff --git a/src/native/corehost/hostpolicy/deps_format.cpp b/src/native/corehost/hostpolicy/deps_format.cpp index 8c91c9fa84bbae..db0417db6e060d 100644 --- a/src/native/corehost/hostpolicy/deps_format.cpp +++ b/src/native/corehost/hostpolicy/deps_format.cpp @@ -94,7 +94,7 @@ deps_json_t::rid_fallback_graph_t deps_json_t::get_rid_fallback_graph(const pal: return rid_fallback_graph; json_parser_t json; - if (!json.parse_file(deps_path_local)) + if (!json.parse_fully_trusted_file(deps_path_local)) return rid_fallback_graph; populate_rid_fallback_graph(json.document(), rid_fallback_graph); @@ -591,7 +591,7 @@ void deps_json_t::load(bool is_framework_dependent, std::function>(data); -#else // _WIN32 - m_document.ParseInsitu(data); -#endif // _WIN32 + + // Can't use in-situ parsing, as RapidJson requires a null-terminated string, + // and the provided data may not be null-terminated. The input data is always + // expected to be UTF-8 encoded; m_document is initialized with the appropriate + // encoding type for the underlying OS (UTF-16 on Windows; UTF-8 elsewhere). + m_document.Parse>(data, size); if (m_document.HasParseError()) { @@ -82,18 +82,19 @@ bool json_parser_t::parse_raw_data(char* data, int64_t size, const pal::string_t return true; } -bool json_parser_t::parse_file(const pal::string_t& path) +bool json_parser_t::parse_fully_trusted_file(const pal::string_t& path) { // This code assumes that the caller has checked that the file `path` exists - // either within the bundle, or as a real file on disk. + // either within the bundle, or as a real file on disk. It also assumes + // that the contents of the target file are fully trusted; that is, that no + // portion of its contents has been provided by a hostile agent. + assert(m_data == nullptr); assert(m_bundle_location == nullptr); if (bundle::info_t::is_single_file_bundle()) { - // Due to in-situ parsing on Linux, - // * The json file is mapped as copy-on-write. - // * The mapping cannot be immediately released, and will be unmapped by the json_parser destructor. + // The mapping cannot be immediately released; it will be unmapped by the json_parser destructor. m_data = bundle::info_t::config_t::map(path, m_bundle_location); if (m_data != nullptr) @@ -104,14 +105,7 @@ bool json_parser_t::parse_file(const pal::string_t& path) if (m_data == nullptr) { -#ifdef _WIN32 - // We can't use in-situ parsing on Windows, as JSON data is encoded in - // UTF-8 and the host expects wide strings. - // We do not need copy-on-write, so read-only mapping will be enough. m_data = (char*)pal::mmap_read(path, &m_size); -#else // _WIN32 - m_data = (char*)pal::mmap_copy_on_write(path, &m_size); -#endif // _WIN32 if (m_data == nullptr) { @@ -130,7 +124,7 @@ bool json_parser_t::parse_file(const pal::string_t& path) data += 3; } - return parse_raw_data(data, size, path); + return parse_fully_trusted_raw_data(data, size, path); } json_parser_t::~json_parser_t() diff --git a/src/native/corehost/json_parser.h b/src/native/corehost/json_parser.h index 0ef5e66575f474..8bc2689395f1b5 100644 --- a/src/native/corehost/json_parser.h +++ b/src/native/corehost/json_parser.h @@ -37,8 +37,8 @@ class json_parser_t { const document_t& document() const { return m_document; } const pal::string_t& get_error_message() const { return m_parse_error; } - bool parse_raw_data(char* data, int64_t size, const pal::string_t& context); - bool parse_file(const pal::string_t& path); + bool parse_fully_trusted_raw_data(char* data, size_t size, const pal::string_t& context); + bool parse_fully_trusted_file(const pal::string_t& path); json_parser_t() : m_data(nullptr) diff --git a/src/native/corehost/runtime_config.cpp b/src/native/corehost/runtime_config.cpp index 740c46aa59e2d3..1e5fa17e2437d0 100644 --- a/src/native/corehost/runtime_config.cpp +++ b/src/native/corehost/runtime_config.cpp @@ -357,7 +357,7 @@ bool runtime_config_t::ensure_dev_config_parsed() // runtimeconfig.dev.json is never bundled into the single-file app. // So, only a file on disk is processed. json_parser_t json; - if (!json.parse_file(m_dev_path)) + if (!json.parse_fully_trusted_file(m_dev_path)) { return false; } @@ -411,7 +411,7 @@ bool runtime_config_t::ensure_parsed() } json_parser_t json; - if (!json.parse_file(m_path)) + if (!json.parse_fully_trusted_file(m_path)) { trace::error(_X("Failed to parse file [%s]. %s"), m_path.c_str(), json.get_error_message().c_str()); return false;