Skip to content
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

RuntimeError: float unrepresentable in integer range #83

Closed
kzc opened this issue May 3, 2020 · 1 comment
Closed

RuntimeError: float unrepresentable in integer range #83

kzc opened this issue May 3, 2020 · 1 comment

Comments

@kzc
Copy link
Contributor

kzc commented May 3, 2020

Using esbuild-wasm@0.1.22:

$ echo 'console.log(0x8000000000000000, 9223372036854776000)' | node
9223372036854776000 9223372036854776000
$ echo 'console.log(0x8000000000000000, 9223372036854776000)' | esbuild-minify 
wasm-0112482e:997

RuntimeError: float unrepresentable in integer range
    at runtime.wasmTruncS (wasm-function[996]:0xce0ae)
    at esbuild_printer.__printer_.printExpr (wasm-function[2440]:0x2466eb)

Context:

function readVarint() {
    var buf = this.buf, val, b, b0, b1, b2, b3;
    b0 = buf[this.pos++]; if (b0 < 0x80) return b0;                 b0 = b0 & 0x7f;
    b1 = buf[this.pos++]; if (b1 < 0x80) return b0 | b1 << 7;       b1 = (b1 & 0x7f) << 7; 
    b2 = buf[this.pos++]; if (b2 < 0x80) return b0 | b1 | b2 << 14; b2 = (b2 & 0x7f) << 14;
    b3 = buf[this.pos++]; if (b3 < 0x80) return b0 | b1 | b2 | b3 << 21; 
    val = b0 | b1 | b2 | (b3 & 0x7f) << 21;
    b = buf[this.pos++]; val += (b & 0x7f) * 0x10000000;         if (b < 0x80) return val; 
    b = buf[this.pos++]; val += (b & 0x7f) * 0x800000000;        if (b < 0x80) return val; 
    b = buf[this.pos++]; val += (b & 0x7f) * 0x40000000000;      if (b < 0x80) return val; 
    b = buf[this.pos++]; val += (b & 0x7f) * 0x2000000000000;    if (b < 0x80) return val; 
    b = buf[this.pos++]; val += (b & 0x7f) * 0x100000000000000;  if (b < 0x80) return val; 
    b = buf[this.pos++]; val += (b & 0x7f) * 0x8000000000000000; if (b < 0x80) return val;
    throw new Error('Expected varint not more than 10 bytes'); 
}           
@evanw
Copy link
Owner

evanw commented May 3, 2020

Wow, good find.

This appears to be an off-by-one error in the Go WebAssembly runtime itself, in the implementation of runtime.wasmTruncS. It avoids calling the WebAssembly opcode i64.trunc_f64_s if the value is outside the range -0x8000_0000_0000_0000 to 0x7fff_ffff_ffff_ffff, since that will cause this trap:

The problem is that these values are outside the range where 64-bit floats can represent every integer, so 0x7fff_ffff_ffff_ffff is the same floating-point value as 0x8000_0000_0000_0000 (and many other nearby integers). Basically many integers both inside and outside the range map to that floating-point value. It looks like all major JavaScript VMs consider that floating-point value outside the range.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants