diff options
author | Sadie Powell <sadie@witchery.services> | 2025-05-05 16:51:47 +0100 |
---|---|---|
committer | Sadie Powell <sadie@witchery.services> | 2025-05-05 16:53:03 +0100 |
commit | c5ad774ce5dd51ea2e6e09374901f583b9857d7f (patch) | |
tree | cf5b03ab195e427f637216ad68aeb6c0ce106e31 /modules | |
parent | 1321f4f0711b8d0fc799f3d0ea114984083a2c11 (diff) |
Add a workaround for JavaScript truncating integers in RPC.
Diffstat (limited to 'modules')
-rw-r--r-- | modules/rpc/jsonrpc.cpp | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/modules/rpc/jsonrpc.cpp b/modules/rpc/jsonrpc.cpp index 163658495..189e2b3a8 100644 --- a/modules/rpc/jsonrpc.cpp +++ b/modules/rpc/jsonrpc.cpp @@ -86,6 +86,9 @@ private: } public: + // The number of bits that can be represented using the native integer type. + static unsigned integer_bits; + JSONRPCServiceInterface(Module *creator) : RPC::ServiceInterface(creator) , HTTPPage("/jsonrpc", "application/json") @@ -236,16 +239,39 @@ yyjson_mut_val *JSONRPCServiceInterface::SerializeElement(yyjson_mut_doc *doc, c }, [&doc, &elem](int64_t i) { - elem = yyjson_mut_int(doc, i); + auto bits = std::floor(std::log2(abs(i))) + 1; + if (bits <= integer_bits) + { + // We can fit this into an integer. + elem = yyjson_mut_int(doc, i); + } + else + { + // We need to convert this to a string. + auto s = Anope::ToString(i); + elem = yyjson_mut_strncpy(doc, s.c_str(), s.length()); + } }, [&doc, &elem](uint64_t u) { - elem = yyjson_mut_uint(doc, u); + auto bits = std::floor(std::log2(u)) + 1; + if (bits <= integer_bits) + { + // We can fit this into an integer. + elem = yyjson_mut_uint(doc, u); + } + else + { + // We need to convert this to a string. + auto s = Anope::ToString(u); + elem = yyjson_mut_strncpy(doc, s.c_str(), s.length()); + } }, }, value.Get()); return elem; } +unsigned JSONRPCServiceInterface::integer_bits = 64; class ModuleJSONRPC final : public Module @@ -273,6 +299,8 @@ public: httpref->UnregisterPage(&jsonrpcinterface); const auto &modconf = conf.GetModule(this); + JSONRPCServiceInterface::integer_bits = modconf.Get<unsigned>("integer_bits", "64"); + this->httpref = ServiceReference<HTTPProvider>("HTTPProvider", modconf.Get<const Anope::string>("server", "httpd/main")); if (!httpref) throw ConfigException("Unable to find http reference, is httpd loaded?"); |