Skip to content

Commit

Permalink
UInt128: Throw DivideByZeroException when divisor is 0 (#94640)
Browse files Browse the repository at this point in the history
* UInt128: Throw DivideByZeroException when divisor is 0

* Use ThrowHelper and avoid double check
  • Loading branch information
manandre committed Nov 13, 2023
1 parent 0cfad56 commit 1e4d36d
Show file tree
Hide file tree
Showing 12 changed files with 65 additions and 3 deletions.
Expand Up @@ -470,6 +470,12 @@ internal static void ThrowOutOfMemoryException()
throw new OutOfMemoryException();
}

[DoesNotReturn]
internal static void ThrowDivideByZeroException()
{
throw new DivideByZeroException();
}

[DoesNotReturn]
internal static void ThrowOutOfMemoryException_StringTooLong()
{
Expand Down
14 changes: 11 additions & 3 deletions src/libraries/System.Private.CoreLib/src/System/UInt128.cs
Expand Up @@ -1091,10 +1091,18 @@ public static UInt128 Log2(UInt128 value)
/// <inheritdoc cref="IDivisionOperators{TSelf, TOther, TResult}.op_Division(TSelf, TOther)" />
public static UInt128 operator /(UInt128 left, UInt128 right)
{
if ((right._upper == 0) && (left._upper == 0))
if (right._upper == 0)
{
// left and right are both uint64
return left._lower / right._lower;
if (right._lower == 0)
{
ThrowHelper.ThrowDivideByZeroException();
}

if (left._upper == 0)
{
// left and right are both uint64
return left._lower / right._lower;
}
}

if (right >= left)
Expand Down
Expand Up @@ -1082,7 +1082,9 @@ public static void op_DivisionTest()
Assert.Equal(new Int128(0xC000_0000_0000_0000, 0x0000_0000_0000_0000), DivisionOperatorsHelper<Int128, Int128, Int128>.op_Division(MinValue, 2));
Assert.Equal(Zero, DivisionOperatorsHelper<Int128, Int128, Int128>.op_Division(NegativeOne, 2));

Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<Int128, Int128, Int128>.op_Division(Zero, 0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<Int128, Int128, Int128>.op_Division(One, 0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<Int128, Int128, Int128>.op_Division(MaxValue, 0));
}

[Fact]
Expand All @@ -1094,7 +1096,9 @@ public static void op_CheckedDivisionTest()
Assert.Equal(new Int128(0xC000_0000_0000_0000, 0x0000_0000_0000_0000), DivisionOperatorsHelper<Int128, Int128, Int128>.op_CheckedDivision(MinValue, 2));
Assert.Equal(Zero, DivisionOperatorsHelper<Int128, Int128, Int128>.op_CheckedDivision(NegativeOne, 2));

Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<Int128, Int128, Int128>.op_CheckedDivision(Zero, 0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<Int128, Int128, Int128>.op_CheckedDivision(One, 0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<Int128, Int128, Int128>.op_CheckedDivision(MaxValue, 0));
}

//
Expand Down
Expand Up @@ -1031,7 +1031,9 @@ public static void op_DivisionTest()
Assert.Equal(unchecked((short)0xC000), DivisionOperatorsHelper<short, short, short>.op_Division(unchecked((short)0x8000), (short)2));
Assert.Equal((short)0x0000, DivisionOperatorsHelper<short, short, short>.op_Division(unchecked((short)0xFFFF), (short)2));

Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<short, short, short>.op_Division((short)0x0000, (short)0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<short, short, short>.op_Division((short)0x0001, (short)0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<short, short, short>.op_Division(unchecked((short)0xFFFF), (short)0));
}

[Fact]
Expand All @@ -1043,7 +1045,9 @@ public static void op_CheckedDivisionTest()
Assert.Equal(unchecked((short)0xC000), DivisionOperatorsHelper<short, short, short>.op_CheckedDivision(unchecked((short)0x8000), (short)2));
Assert.Equal((short)0x0000, DivisionOperatorsHelper<short, short, short>.op_CheckedDivision(unchecked((short)0xFFFF), (short)2));

Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<short, short, short>.op_CheckedDivision((short)0x0000, (short)0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<short, short, short>.op_CheckedDivision((short)0x0001, (short)0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<short, short, short>.op_CheckedDivision(unchecked((short)0xFFFF), (short)0));
}

//
Expand Down
Expand Up @@ -1031,7 +1031,9 @@ public static void op_DivisionTest()
Assert.Equal(unchecked((int)0xC0000000), DivisionOperatorsHelper<int, int, int>.op_Division(unchecked((int)0x80000000), 2));
Assert.Equal((int)0x00000000, DivisionOperatorsHelper<int, int, int>.op_Division(unchecked((int)0xFFFFFFFF), 2));

Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<int, int, int>.op_Division((int)0x00000000, 0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<int, int, int>.op_Division((int)0x00000001, 0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<int, int, int>.op_Division(unchecked((int)0xFFFFFFFF), 0));
}

[Fact]
Expand All @@ -1043,7 +1045,9 @@ public static void op_CheckedDivisionTest()
Assert.Equal(unchecked((int)0xC0000000), DivisionOperatorsHelper<int, int, int>.op_CheckedDivision(unchecked((int)0x80000000), 2));
Assert.Equal((int)0x00000000, DivisionOperatorsHelper<int, int, int>.op_CheckedDivision(unchecked((int)0xFFFFFFFF), 2));

Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<int, int, int>.op_CheckedDivision((int)0x00000000, 0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<int, int, int>.op_CheckedDivision((int)0x00000001, 0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<int, int, int>.op_CheckedDivision(unchecked((int)0xFFFFFFFF), 0));
}

//
Expand Down
Expand Up @@ -1031,7 +1031,9 @@ public static void op_DivisionTest()
Assert.Equal(unchecked((long)0xC000000000000000), DivisionOperatorsHelper<long, long, long>.op_Division(unchecked((long)0x8000000000000000), 2));
Assert.Equal((long)0x0000000000000000, DivisionOperatorsHelper<long, long, long>.op_Division(unchecked((long)0xFFFFFFFFFFFFFFFF), 2));

Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<long, long, long>.op_Division((long)0x0000000000000000, 0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<long, long, long>.op_Division((long)0x0000000000000001, 0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<long, long, long>.op_Division(unchecked((long)0xFFFFFFFFFFFFFFFF), 0));
}

[Fact]
Expand All @@ -1043,7 +1045,9 @@ public static void op_CheckedDivisionTest()
Assert.Equal(unchecked((long)0xC000000000000000), DivisionOperatorsHelper<long, long, long>.op_CheckedDivision(unchecked((long)0x8000000000000000), 2));
Assert.Equal((long)0x0000000000000000, DivisionOperatorsHelper<long, long, long>.op_CheckedDivision(unchecked((long)0xFFFFFFFFFFFFFFFF), 2));

Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<long, long, long>.op_CheckedDivision((long)0x0000000000000000, 0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<long, long, long>.op_CheckedDivision((long)0x0000000000000001, 0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<long, long, long>.op_CheckedDivision(unchecked((long)0xFFFFFFFFFFFFFFFF), 0));
}

//
Expand Down
Expand Up @@ -1448,7 +1448,9 @@ public static void op_DivisionTest()
Assert.Equal(unchecked((nint)0xC000000000000000), DivisionOperatorsHelper<nint, nint, nint>.op_Division(unchecked((nint)0x8000000000000000), (nint)2));
Assert.Equal(unchecked((nint)0x0000000000000000), DivisionOperatorsHelper<nint, nint, nint>.op_Division(unchecked((nint)0xFFFFFFFFFFFFFFFF), (nint)2));

Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<nint, nint, nint>.op_Division(unchecked((nint)0x0000000000000000), (nint)0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<nint, nint, nint>.op_Division(unchecked((nint)0x0000000000000001), (nint)0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<nint, nint, nint>.op_Division(unchecked((nint)0xFFFFFFFFFFFFFFFF), (nint)0));
}
else
{
Expand All @@ -1458,7 +1460,9 @@ public static void op_DivisionTest()
Assert.Equal(unchecked((nint)0xC0000000), DivisionOperatorsHelper<nint, nint, nint>.op_Division(unchecked((nint)0x80000000), (nint)2));
Assert.Equal((nint)0x00000000, DivisionOperatorsHelper<nint, nint, nint>.op_Division(unchecked((nint)0xFFFFFFFF), (nint)2));

Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<nint, nint, nint>.op_Division((nint)0x00000000, (nint)0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<nint, nint, nint>.op_Division((nint)0x00000001, (nint)0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<nint, nint, nint>.op_Division(unchecked((nint)0xFFFFFFFF), (nint)0));
}
}

Expand All @@ -1473,7 +1477,9 @@ public static void op_CheckedDivisionTest()
Assert.Equal(unchecked((nint)0xC000000000000000), DivisionOperatorsHelper<nint, nint, nint>.op_CheckedDivision(unchecked((nint)0x8000000000000000), (nint)2));
Assert.Equal(unchecked((nint)0x0000000000000000), DivisionOperatorsHelper<nint, nint, nint>.op_CheckedDivision(unchecked((nint)0xFFFFFFFFFFFFFFFF), (nint)2));

Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<nint, nint, nint>.op_CheckedDivision(unchecked((nint)0x0000000000000000), (nint)0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<nint, nint, nint>.op_CheckedDivision(unchecked((nint)0x0000000000000001), (nint)0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<nint, nint, nint>.op_CheckedDivision(unchecked((nint)0xFFFFFFFFFFFFFFFF), (nint)0));
}
else
{
Expand All @@ -1483,7 +1489,9 @@ public static void op_CheckedDivisionTest()
Assert.Equal(unchecked((nint)0xC0000000), DivisionOperatorsHelper<nint, nint, nint>.op_CheckedDivision(unchecked((nint)0x80000000), (nint)2));
Assert.Equal((nint)0x00000000, DivisionOperatorsHelper<nint, nint, nint>.op_CheckedDivision(unchecked((nint)0xFFFFFFFF), (nint)2));

Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<nint, nint, nint>.op_CheckedDivision((nint)0x00000000, (nint)0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<nint, nint, nint>.op_CheckedDivision((nint)0x00000001, (nint)0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<nint, nint, nint>.op_CheckedDivision(unchecked((nint)0xFFFFFFFF), (nint)0));
}
}

Expand Down
Expand Up @@ -1082,7 +1082,9 @@ public static void op_DivisionTest()
Assert.Equal(new UInt128(0x4000_0000_0000_0000, 0x0000_0000_0000_0000), DivisionOperatorsHelper<UInt128, UInt128, UInt128>.op_Division(Int128MaxValuePlusOne, 2U));
Assert.Equal(Int128MaxValue, DivisionOperatorsHelper<UInt128, UInt128, UInt128>.op_Division(MaxValue, 2U));

Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<UInt128, UInt128, UInt128>.op_Division(Zero, 0U));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<UInt128, UInt128, UInt128>.op_Division(One, 0U));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<UInt128, UInt128, UInt128>.op_Division(MaxValue, 0U));
}

[Fact]
Expand All @@ -1094,7 +1096,9 @@ public static void op_CheckedDivisionTest()
Assert.Equal(new UInt128(0x4000_0000_0000_0000, 0x0000_0000_0000_0000), DivisionOperatorsHelper<UInt128, UInt128, UInt128>.op_CheckedDivision(Int128MaxValuePlusOne, 2U));
Assert.Equal(Int128MaxValue, DivisionOperatorsHelper<UInt128, UInt128, UInt128>.op_CheckedDivision(MaxValue, 2U));

Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<UInt128, UInt128, UInt128>.op_CheckedDivision(Zero, 0U));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<UInt128, UInt128, UInt128>.op_CheckedDivision(One, 0U));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<UInt128, UInt128, UInt128>.op_CheckedDivision(MaxValue, 0U));
}

//
Expand Down
Expand Up @@ -1032,7 +1032,9 @@ public static void op_DivisionTest()
Assert.Equal((ushort)0x4000, DivisionOperatorsHelper<ushort, ushort, ushort>.op_Division((ushort)0x8000, (ushort)2));
Assert.Equal((ushort)0x7FFF, DivisionOperatorsHelper<ushort, ushort, ushort>.op_Division((ushort)0xFFFF, (ushort)2));

Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<ushort, ushort, ushort>.op_Division((ushort)0x0000, (ushort)0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<ushort, ushort, ushort>.op_Division((ushort)0x0001, (ushort)0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<ushort, ushort, ushort>.op_Division((ushort)0xFFFF, (ushort)0));
}

[Fact]
Expand All @@ -1044,7 +1046,9 @@ public static void op_CheckedDivisionTest()
Assert.Equal((ushort)0x4000, DivisionOperatorsHelper<ushort, ushort, ushort>.op_CheckedDivision((ushort)0x8000, (ushort)2));
Assert.Equal((ushort)0x7FFF, DivisionOperatorsHelper<ushort, ushort, ushort>.op_CheckedDivision((ushort)0xFFFF, (ushort)2));

Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<ushort, ushort, ushort>.op_CheckedDivision((ushort)0x0000, (ushort)0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<ushort, ushort, ushort>.op_CheckedDivision((ushort)0x0001, (ushort)0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<ushort, ushort, ushort>.op_CheckedDivision((ushort)0xFFFF, (ushort)0));
}

//
Expand Down
Expand Up @@ -1033,7 +1033,9 @@ public static void op_DivisionTest()
Assert.Equal((uint)0x40000000, DivisionOperatorsHelper<uint, uint, uint>.op_Division((uint)0x80000000, 2));
Assert.Equal((uint)0x7FFFFFFF, DivisionOperatorsHelper<uint, uint, uint>.op_Division((uint)0xFFFFFFFF, 2));

Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<uint, uint, uint>.op_Division((uint)0x00000000, 0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<uint, uint, uint>.op_Division((uint)0x00000001, 0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<uint, uint, uint>.op_Division((uint)0xFFFFFFFF, 0));
}

[Fact]
Expand All @@ -1045,7 +1047,9 @@ public static void op_CheckedDivisionTest()
Assert.Equal((uint)0x40000000, DivisionOperatorsHelper<uint, uint, uint>.op_CheckedDivision((uint)0x80000000, 2));
Assert.Equal((uint)0x7FFFFFFF, DivisionOperatorsHelper<uint, uint, uint>.op_CheckedDivision((uint)0xFFFFFFFF, 2));

Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<uint, uint, uint>.op_CheckedDivision((uint)0x00000000, 0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<uint, uint, uint>.op_CheckedDivision((uint)0x00000001, 0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<uint, uint, uint>.op_CheckedDivision((uint)0xFFFFFFFF, 0));
}

//
Expand Down
Expand Up @@ -1032,7 +1032,9 @@ public static void op_DivisionTest()
Assert.Equal((ulong)0x4000000000000000, DivisionOperatorsHelper<ulong, ulong, ulong>.op_Division((ulong)0x8000000000000000, 2));
Assert.Equal((ulong)0x7FFFFFFFFFFFFFFF, DivisionOperatorsHelper<ulong, ulong, ulong>.op_Division((ulong)0xFFFFFFFFFFFFFFFF, 2));

Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<ulong, ulong, ulong>.op_Division((ulong)0x0000000000000000, 0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<ulong, ulong, ulong>.op_Division((ulong)0x0000000000000001, 0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<ulong, ulong, ulong>.op_Division((ulong)0xFFFFFFFFFFFFFFFF, 0));
}

[Fact]
Expand All @@ -1044,7 +1046,9 @@ public static void op_CheckedDivisionTest()
Assert.Equal((ulong)0x4000000000000000, DivisionOperatorsHelper<ulong, ulong, ulong>.op_CheckedDivision((ulong)0x8000000000000000, 2));
Assert.Equal((ulong)0x7FFFFFFFFFFFFFFF, DivisionOperatorsHelper<ulong, ulong, ulong>.op_CheckedDivision((ulong)0xFFFFFFFFFFFFFFFF, 2));

Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<ulong, ulong, ulong>.op_CheckedDivision((ulong)0x0000000000000000, 0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<ulong, ulong, ulong>.op_CheckedDivision((ulong)0x0000000000000001, 0));
Assert.Throws<DivideByZeroException>(() => DivisionOperatorsHelper<ulong, ulong, ulong>.op_CheckedDivision((ulong)0xFFFFFFFFFFFFFFFF, 0));
}

//
Expand Down

0 comments on commit 1e4d36d

Please sign in to comment.