Skip to content

Commit 0ffd606

Browse files
authored
Resolved an arithmetic overflow error in Decimal division caused by improper upcasting (#850)
- Upcast numbers to higher bitwidth before performing calculations. resolves: rdar://133458109 resolves: #595
1 parent aecc1b1 commit 0ffd606

File tree

2 files changed

+27
-2
lines changed

2 files changed

+27
-2
lines changed

Sources/FoundationEssentials/Decimal/Decimal+Math.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -949,7 +949,7 @@ extension Decimal {
949949

950950
// D1: Normalize
951951
// Calculate d such that `d*highest_dight_of_divisor >= b/2 (0x8000)
952-
let d = (1 << 16) / UInt32(divisor[divisor.count - 1] + 1)
952+
let d: UInt32 = (1 << 16) / (UInt32(divisor[divisor.count - 1]) + 1)
953953
// This is to make the whole algorithm work and
954954
// (dividend * d) / (divisor * d) == dividend / divisor
955955
var normalizedDividend = try self._integerMultiplyByShort(

Tests/FoundationEssentialsTests/DecimalTests.swift

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,32 @@ final class DecimalTests : XCTestCase {
613613
XCTAssertTrue(Decimal._compare(lhs: expected, rhs: result) == .orderedSame)
614614
}
615615

616+
func testCrashingDivision() throws {
617+
// This test makes sure the following division
618+
// does not crash
619+
let first: Decimal = Decimal(1147858867)
620+
let second: Decimal = Decimal(4294967295)
621+
let result = first / second
622+
let expected: Decimal = Decimal(
623+
_exponent: -38,
624+
_length: 8,
625+
_isNegative: 0,
626+
_isCompact: 1,
627+
_reserved: 0,
628+
_mantissa: (
629+
58076,
630+
13229,
631+
12316,
632+
25502,
633+
15252,
634+
32996,
635+
11611,
636+
5147
637+
)
638+
)
639+
XCTAssertEqual(result, expected)
640+
}
641+
616642
func testPower() throws {
617643
var a = Decimal(1234)
618644
var result = try a._power(exponent: 0, roundingMode: .plain)
@@ -1272,5 +1298,4 @@ final class DecimalTests : XCTestCase {
12721298
XCTAssertEqual(length, 3)
12731299
}
12741300
#endif
1275-
12761301
}

0 commit comments

Comments
 (0)