From b271cefea1abca6a38216b8e9c909b2b34c2511b Mon Sep 17 00:00:00 2001 From: Conic Games <64161905+conicgames@users.noreply.github.com> Date: Wed, 16 Feb 2022 13:17:20 -0500 Subject: [PATCH] Fix integer addition/subtraction overflow (#1091) --- Jint.Tests/Runtime/EngineTests.cs | 16 ++++++++++++++++ Jint/Native/JsNumber.cs | 6 +++--- .../Expressions/JintBinaryExpression.cs | 4 ++-- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/Jint.Tests/Runtime/EngineTests.cs b/Jint.Tests/Runtime/EngineTests.cs index 92772a70aa..08d92a1998 100644 --- a/Jint.Tests/Runtime/EngineTests.cs +++ b/Jint.Tests/Runtime/EngineTests.cs @@ -547,6 +547,22 @@ public void NaNIsNan() "); } + [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() { diff --git a/Jint/Native/JsNumber.cs b/Jint/Native/JsNumber.cs index 5ca963f0ff..7fdc3573ad 100644 --- a/Jint/Native/JsNumber.cs +++ b/Jint/Native/JsNumber.cs @@ -58,17 +58,17 @@ public JsNumber(int value) : base(InternalTypes.Integer) _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; } diff --git a/Jint/Runtime/Interpreter/Expressions/JintBinaryExpression.cs b/Jint/Runtime/Interpreter/Expressions/JintBinaryExpression.cs index 01cc3bf881..961873cd28 100644 --- a/Jint/Runtime/Interpreter/Expressions/JintBinaryExpression.cs +++ b/Jint/Runtime/Interpreter/Expressions/JintBinaryExpression.cs @@ -268,7 +268,7 @@ protected override ExpressionResult EvaluateInternal(EvaluationContext context) 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 @@ protected override ExpressionResult EvaluateInternal(EvaluationContext context) if (AreIntegerOperands(left, right)) { - number = JsNumber.Create(left.AsInteger() - right.AsInteger()); + number = JsNumber.Create((long)left.AsInteger() - right.AsInteger()); } else if (AreNonBigIntOperands(left, right)) {