-
Notifications
You must be signed in to change notification settings - Fork 95
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JS_ToBigInt64 handles overflow incorrectly #364
Comments
Interesting! I guess there is no test that checks for this. A good first step would be to add one that fails. |
Here is a Rust example: https://github.com/Icemic/quickjspp-rs/blob/221fff9e177fa5b490bf349aa74f3550eb7f0397/tests/runtime.rs#L641
|
Hello @Icemic, nice to see QuickJS used in the rust world... I don't understand your point:
It follows the ECMA spec: 7.1.15 ToBigInt64 ( argument ). You seem to expect some other behavior, what is your use case ? |
Thanks for the reply! I hadn't noticed the ECMA spec aspect before. Given that this function adheres to an established specification, it should indeed be fine. I'm maintaining a QuickJS to Rust binding, which is forked from quickjs-rs. There's a piece of code designed to extract the actual value from a JSValue tagged as bigint, and then convert it into a Rust type: https://github.com/Icemic/quickjspp-rs/blob/221fff9e177fa5b490bf349aa74f3550eb7f0397/src/value/value.rs#L276-L306 Its approach begins with an attempt to convert using So, my question now shifts to: In similar binding libraries or FFI scenarios, what is the recommended way to retrieve and convert values from a TAG_BIGINIT type JSValue to a native type? |
I would recommend adding these APIs:
With these your can determine if For efficient conversions to and from another language native representation, I would add these:
The current implementation uses a general floating point representation that makes these conversion APIs non trivial but still much faster than a string conversion. We are likely to change the internal representation in the near future to make this API straightforward. |
JS_ToBigInt64
handles number larger than 2^64 incorrectly.Divive into the function, it calls
JS_ToBigInt64Free
thenJS_ToBigInt64Free
:For numbers larger than 2^64,
a
has a valid value so it goes tobf_get_int64
where the problem occurs.For example, the number
2^64 + 2
, itsa->expn
is64
. While usingBF_GET_INT_MOD
flag, it goes to the finalelse
block.As
BF_GET_INT_MOD
implies thatmodulo 2^n instead of saturation. NaN and infinity return 0
, finally we got thev
as2
which is from(2^64 + 2) % 2^64
, andret=0
which meansreturns a right result
.Then everything mess up.
That is to say that we cannot judge the return value from
JS_ToBigInt64Free
(as well asJS_ToBigInt64
) whether it is the actual result or the actual result mods 2^64It seems to be a problem that has been around for a long time, and a solution has already been suggested: https://github.com/theduke/quickjs-rs/blob/master/libquickjs-sys/embed/patches/js-tobigint64-overflow.patch
I've tried to apply the patch and the problem goes fixed.
So I think maybe it should be adopted?
The text was updated successfully, but these errors were encountered: