From 9563a1009da87ed6faa2c34adcd853caac7fac03 Mon Sep 17 00:00:00 2001 From: Yarchik Date: Tue, 30 Jun 2026 12:43:36 +0100 Subject: [PATCH] fix: correct wasm div of negative high-word dividend by -1 The wasm-backed signed division short-circuits and returns the dividend unchanged whenever this.high === 0x80000000 and the divisor is -1. That guard is meant to catch only the true two's-complement overflow of MIN_VALUE / -1, but it omits the low-word check, so any negative dividend sharing that high word (for example -9223372036854775807) is wrongly returned unchanged instead of being negated. Add this.low === 0 so only the exact MIN_VALUE / -1 overflow is special cased; every other value falls through to wasm.div_s. This matches the non-wasm path, which guards on this.eq(MIN_VALUE). --- index.js | 1 + tests/index.js | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/index.js b/index.js index 4983233..8306b9f 100644 --- a/index.js +++ b/index.js @@ -1060,6 +1060,7 @@ LongPrototype.divide = function divide(divisor) { // positive number, due to two's complement. if ( !this.unsigned && + this.low === 0 && this.high === -0x80000000 && divisor.low === -1 && divisor.high === -1 diff --git a/tests/index.js b/tests/index.js index 3eab85e..53b4471 100644 --- a/tests/index.js +++ b/tests/index.js @@ -178,6 +178,23 @@ var tests = [ assert.strictEqual(longVal.toString(), Long.MIN_VALUE.toString()); }, + function testSignedNegHighWordDivNegOne() { + // A negative dividend whose high word is 0x80000000 but whose low word is + // non-zero must negate correctly when divided by -1. Only the exact + // MIN_VALUE / -1 is a true two's-complement overflow. + assert.strictEqual( + Long.fromString("-9223372036854775807").div(Long.fromInt(-1)).toString(), + "9223372036854775807", + ); + assert.strictEqual( + Long.fromString("-9223372036854775296").div(Long.fromInt(-1)).toString(), + "9223372036854775296", + ); + // The exact MIN_VALUE / -1 overflow still wraps to MIN_VALUE. + var overflow = Long.MIN_VALUE.div(Long.fromInt(-1)); + assert.strictEqual(overflow.toString(), Long.MIN_VALUE.toString()); + }, + function testUnsignedMsbUnsigned() { var longVal = Long.UONE.shiftLeft(63); assert.strictEqual(longVal.notEquals(Long.MIN_VALUE), true);