From e134121f5844a4f15a10f710ca788de9f21b65c2 Mon Sep 17 00:00:00 2001 From: tens0rfl0w Date: Tue, 1 Oct 2024 18:24:09 +0200 Subject: [PATCH] fix(msgpack): JSON map conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes various unhandled exceptions when trying to convert a msgpack map object to a JSON object: - Out-ouf-bounds exception handling when key type is int - Duplicate key check (when converting from int->string) - Invalid type as key -> type ≠ string, int, bin --- code/client/shared/MsgpackJson.h | 63 ++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/code/client/shared/MsgpackJson.h b/code/client/shared/MsgpackJson.h index 4030f8b312..189e04f098 100644 --- a/code/client/shared/MsgpackJson.h +++ b/code/client/shared/MsgpackJson.h @@ -3,6 +3,8 @@ #include #include +#include + inline void ConvertToMsgPack(const rapidjson::Value& json, msgpack::object& object, msgpack::zone& zone) { switch (json.GetType()) @@ -143,35 +145,56 @@ inline void ConvertToJSON(const msgpack::object& object, rapidjson::Value& value case msgpack::type::MAP: { - std::map list; + value.SetObject(); if (object.via.map.ptr) { - if (object.via.map.ptr->key.type == msgpack::type::STR) - { - object.convert(list); - } - else + auto p = object.via.map.ptr; + const auto pend = p + object.via.map.size; + + for (; p < pend; ++p) { - auto intList = object.as>(); - for (auto& [key, value] : intList) + std::string key; + + if (p->key.type == msgpack::type::POSITIVE_INTEGER || p->key.type == msgpack::type::NEGATIVE_INTEGER) { - list[std::to_string(key)] = std::move(value); + try + { + key = std::to_string(p->key.as()); + } + catch (const msgpack::type_error&) + { + console::PrintError("msgpack-json", "Key out of integer range\n"); + value.SetObject(); + break; + } + } + else if (p->key.type == msgpack::type::STR || p->key.type == msgpack::type::BIN) + { + key = p->key.as(); } - } - } - - value.SetObject(); + else + { + console::PrintError("msgpack-json", "Unsupported key type: %d\n", p->key.type); + value.SetObject(); + break; + } - for (auto& entry : list) - { - rapidjson::Value inValue; - ConvertToJSON(entry.second, inValue, allocator); + rapidjson::Value name; + name.SetString(key.c_str(), key.size(), allocator); - rapidjson::Value name; - name.SetString(entry.first.c_str(), entry.first.size(), allocator); + if (value.HasMember(name)) + { + console::PrintError("msgpack-json", "Duplicate key: %s\n", key); + value.SetObject(); + break; + } + + rapidjson::Value inValue; + ConvertToJSON(p->val, inValue, allocator); - value.AddMember(name, inValue, allocator); + value.AddMember(name, inValue, allocator); + } } break;