Browse Source

Fix for #7485 - Int32 negate missing clamp (#7491)

Jeff Ward 6 years ago
parent
commit
2a48e2c049
3 changed files with 30 additions and 2 deletions
  1. 1 1
      std/haxe/Int32.hx
  2. 23 0
      tests/unit/src/unit/TestInt64.hx
  3. 6 1
      tests/unit/src/unitstd/haxe/Int32.unit.hx

+ 1 - 1
std/haxe/Int32.hx

@@ -26,7 +26,7 @@
  	all platforms.
  **/
 abstract Int32(Int) from Int to Int {
-	@:op(-A) private function negate():Int32;
+	@:op(-A) private inline function negate():Int32 return clamp(~this+1);
 
 	@:op(++A) private inline function preIncrement():Int32
 		return this = clamp(++this);

+ 23 - 0
tests/unit/src/unit/TestInt64.hx

@@ -38,6 +38,29 @@ class TestInt64 extends Test {
 		exc( tryOverflow.bind(a) );	// Throws Overflow
 	}
 
+	public function testNegateOverflow_Issue7485()
+	{
+		// Guarantee two's complement overflow (-min == min)
+		//  - discussion: https://github.com/HaxeFoundation/haxe/pull/7491
+		var min = haxe.Int64.parseString('-9223372036854775808');
+		eq( min==(-min), true);
+
+		// 0x7fffffff - 0x7fffffffffffffff = -7fffffff80000000
+		var a = haxe.Int64.parseString('2147483647');
+		var b = haxe.Int64.parseString('9223372036854775807');
+		var z = haxe.Int64.sub(a, b);
+		eq(haxe.Int64.toStr(z), "-9223372034707292160");
+
+		// This fails because the first division fails:
+		var ten = haxe.Int64.make(0, 10);
+		var modulus = haxe.Int64.divMod( z, ten ).modulus.low;
+		eq( modulus, 0 );
+
+		// The first division failed because of negate:
+		eq( (-z).low, -2147483648 );
+		eq( (-z).high, 2147483647 );
+	}
+
 	// Some tests of how it generates Int64 when used as Null<Int64> or as type parameters
 	function testGen()
 	{

+ 6 - 1
tests/unit/src/unitstd/haxe/Int32.unit.hx

@@ -43,4 +43,9 @@ i32 == 3;
 var i32:haxe.Int32 = 2;
 var c = ~(((a[next] << 32) | 1):haxe.Int32);
 c == 0xfffffffe;
-#end
+#end
+
+// - see: https://github.com/HaxeFoundation/haxe/pull/7491
+-min == min;              // two's complement overflow,
+-2147483643 == 5 + -min;  // order of ops and negate
+2147483643 == -(5 + min); // static analyzer issue