Skip to content

Commit

Permalink
fix(msgpack): JSON map conversion
Browse files Browse the repository at this point in the history
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
  • Loading branch information
tens0rfl0w committed Oct 3, 2024
1 parent e31630e commit d9188fa
Showing 1 changed file with 44 additions and 21 deletions.
65 changes: 44 additions & 21 deletions code/client/shared/MsgpackJson.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#pragma once

// Trigger Github Actions build
#include <msgpack.hpp>
#include <rapidjson/document.h>

#include <CoreConsole.h>

inline void ConvertToMsgPack(const rapidjson::Value& json, msgpack::object& object, msgpack::zone& zone)
{
switch (json.GetType())
Expand Down Expand Up @@ -143,35 +145,56 @@ inline void ConvertToJSON(const msgpack::object& object, rapidjson::Value& value

case msgpack::type::MAP:
{
std::map<std::string, msgpack::object> 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<std::map<int, msgpack::object>>();
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<int>());
}
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<std::string>();
}
}
}

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;
Expand Down

0 comments on commit d9188fa

Please sign in to comment.