summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorSadie Powell <sadie@witchery.services>2025-05-05 16:51:47 +0100
committerSadie Powell <sadie@witchery.services>2025-05-05 16:53:03 +0100
commitc5ad774ce5dd51ea2e6e09374901f583b9857d7f (patch)
treecf5b03ab195e427f637216ad68aeb6c0ce106e31 /modules
parent1321f4f0711b8d0fc799f3d0ea114984083a2c11 (diff)
Add a workaround for JavaScript truncating integers in RPC.
Diffstat (limited to 'modules')
-rw-r--r--modules/rpc/jsonrpc.cpp32
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?");