1
0
mirror of https://github.com/anope/anope.git synced 2026-07-04 22:13:12 +02:00

Add a workaround for JavaScript truncating integers in RPC.

This commit is contained in:
Sadie Powell
2025-05-05 16:51:47 +01:00
parent 1321f4f071
commit c5ad774ce5
2 changed files with 46 additions and 5 deletions
+16 -3
View File
@@ -810,6 +810,19 @@ module
{
name = "jsonrpc"
/*
* The maximum number of bits an integer can be have in its native type.
*
* By default Anope will emit integers as their native JSON type. If you are
* using JavaScript (which has 56 bit integers) or another language with
* native integer types smaller than 64 bits you may need to limit the size
* of integers emitted by Anope.
*
* If this is enabled a string will be used for values outside of the range
* supported by the native data type.
*/
#integer_bits = 56
/* Web service to use. Requires httpd. */
server = "httpd/main"
@@ -852,9 +865,6 @@ module
{
name = "xmlrpc"
/* Web service to use. Requires httpd. */
server = "httpd/main"
/*
* Whether to enable the use of XML-RPC extensions.
*
@@ -869,6 +879,9 @@ module
#enable_i8 = no
#enable_nil = no
/* Web service to use. Requires httpd. */
server = "httpd/main"
/*
* You can also specify one or more authorization tokens to protect access
* to the XML-RPC interface. These tokens should be sent using the Bearer
+30 -2
View File
@@ -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?");