Bladeren bron

Fix integer addition/subtraction overflow (#1091)

Conic Games 3 jaren geleden
bovenliggende
commit
b271cefea1

+ 16 - 0
Jint.Tests/Runtime/EngineTests.cs

@@ -547,6 +547,22 @@ namespace Jint.Tests.Runtime
             ");
         }
 
+        [Theory]
+        [InlineData(2147483647, 1, 2147483648)]
+        [InlineData(-2147483647, -2, -2147483649)]
+        public void IntegerAdditionShouldNotOverflow(int lhs, int rhs, long result)
+        {
+            RunTest($"assert({lhs} + {rhs} == {result})");
+        }
+
+        [Theory]
+        [InlineData(2147483647, -1, 2147483648)]
+        [InlineData(-2147483647, 2, -2147483649)]
+        public void IntegerSubtractionShouldNotOverflow(int lhs, int rhs, long result)
+        {
+            RunTest($"assert({lhs} - {rhs} == {result})");
+        }
+
         [Fact]
         public void ToNumberHandlesStringObject()
         {

+ 3 - 3
Jint/Native/JsNumber.cs

@@ -58,17 +58,17 @@ namespace Jint.Native
             _value = value;
         }
 
-        public JsNumber(uint value) : base(value < int.MaxValue ? InternalTypes.Integer : InternalTypes.Number)
+        public JsNumber(uint value) : base(value <= int.MaxValue ? InternalTypes.Integer : InternalTypes.Number)
         {
             _value = value;
         }
 
-        public JsNumber(ulong value) : base(value < int.MaxValue ? InternalTypes.Integer : InternalTypes.Number)
+        public JsNumber(ulong value) : base(value <= int.MaxValue ? InternalTypes.Integer : InternalTypes.Number)
         {
             _value = value;
         }
 
-        public JsNumber(long value) : base(value < int.MaxValue && value > int.MinValue ? InternalTypes.Integer : InternalTypes.Number)
+        public JsNumber(long value) : base(value <= int.MaxValue && value >= int.MinValue ? InternalTypes.Integer : InternalTypes.Number)
         {
             _value = value;
         }

+ 2 - 2
Jint/Runtime/Interpreter/Expressions/JintBinaryExpression.cs

@@ -268,7 +268,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
                 if (AreIntegerOperands(left, right))
                 {
-                    return NormalCompletion(JsNumber.Create(left.AsInteger() + right.AsInteger()));
+                    return NormalCompletion(JsNumber.Create((long)left.AsInteger() + right.AsInteger()));
                 }
 
                 var lprim = TypeConverter.ToPrimitive(left);
@@ -315,7 +315,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
                 if (AreIntegerOperands(left, right))
                 {
-                    number = JsNumber.Create(left.AsInteger() - right.AsInteger());
+                    number = JsNumber.Create((long)left.AsInteger() - right.AsInteger());
                 }
                 else if (AreNonBigIntOperands(left, right))
                 {