You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
length_metadata only returns the correct result when len is between -1 << 31 and ~(-1 << 31) (equivalent to Number((1n << 31n) - 1n)), inclusive - i.e., when len fits into a signed 32-bit integer (i32).
As far as I can tell, when applying bitwise operations to an integer Number outside of the range of a signed 32-bit integer, JavaScript first coerces it to a 32-bit signed integer by applying operations equivalent to the following:
Represent the Number as a 64-bit signed integer. (BigInt(n))
Take only the 32 least significant bits (the 4 least significant bytes), discarding the 32 most significant bits. (BigInt(n) & 0xff_ff_ff_ffn)
Intepret these 32 bits as a signed 32-bit integer (i32). (~~Number(BigInt(n) & 0xff_ff_ff_ffn))
(So for a Number n, ~~n should be equal to ~~Number(BigInt(n) & 0xff_ff_ff_ffn).)
Thus, when passing a len that is not an i32 to length_metadata, some of the bits may be discarded, giving the wrong result.
No matter what value of len is passed, length_metadata(len)[4], length_metadata(len)[5], length_metadata(len)[6], and length_metadata(len)[7] will always be equal to 0.
However, the function seems to be broken in another way for inputs outside of the 32-bit range - I am not sure of the exact source this code was taken from, but I would think lines 17 through 26 of index.ts would be the following:
Or adapted to use BigInts to properly handle integers outside the 32-bit range:
if(!Number.isSafeInteger(len))throwRangeError("len is not a safe integer - it may be too large");letbig=BigInt(len);return[(big&0x00000000000000ffn)>>0n,(big&0x000000000000ff00n)>>8n,(big&0x0000000000ff0000n)>>16n,(big&0x00000000ff000000n)>>24n,(big&0x000000ff00000000n)>>32n,(big&0x0000ff0000000000n)>>40n,(big&0x00ff000000000000n)>>48n,(big&0xff00000000000000n)>>56n,].map(n=>Number(n));
The above should be equivalent to the following:
if(!Number.isSafeInteger(len))throwRangeError("len is not a safe integer - it may be too large");letbuf=newArrayBuffer(8);letview=newDataView(buf);view.setBigUint64(0,BigInt(len),true);// write using little-endian (default)return[...newUint8Array(buf)];
The text was updated successfully, but these errors were encountered:
length_metadata
only returns the correct result whenlen
is between-1 << 31
and~(-1 << 31)
(equivalent toNumber((1n << 31n) - 1n)
), inclusive - i.e., whenlen
fits into a signed 32-bit integer (i32
).As far as I can tell, when applying bitwise operations to an integer
Number
outside of the range of a signed 32-bit integer, JavaScript first coerces it to a 32-bit signed integer by applying operations equivalent to the following:Number
as a 64-bit signed integer. (BigInt(n)
)BigInt(n) & 0xff_ff_ff_ffn
)i32
). (~~Number(BigInt(n) & 0xff_ff_ff_ffn)
)(So for a Number
n
,~~n
should be equal to~~Number(BigInt(n) & 0xff_ff_ff_ffn)
.)Thus, when passing a
len
that is not an i32 tolength_metadata
, some of the bits may be discarded, giving the wrong result.No matter what value of
len
is passed,length_metadata(len)[4]
,length_metadata(len)[5]
,length_metadata(len)[6]
, andlength_metadata(len)[7]
will always be equal to 0.However, the function seems to be broken in another way for inputs outside of the 32-bit range - I am not sure of the exact source this code was taken from, but I would think lines 17 through 26 of
index.ts
would be the following:Or adapted to use BigInts to properly handle integers outside the 32-bit range:
The above should be equivalent to the following:
The text was updated successfully, but these errors were encountered: