Skip to content

Commit 9f217d1

Browse files
authored
Merge pull request #1680 from drodriguez/fix-CFHashDouble-undefined-behaviour
Fix UB when hashing some doubles in 32bits.
2 parents 2b18f4d + 9f6290c commit 9f217d1

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

CoreFoundation/Base.subproj/ForFoundationOnly.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ CF_INLINE CFHashCode _CFHashDouble(const double d) {
542542
result += -((CFHashCode)(fabs(fractional)));
543543
} else if (fractional > 0) {
544544
// Caveat: the > 0 is incredibly important [28612173]
545-
result += fractional;
545+
result += (CFHashCode)fractional;
546546
}
547547
return result;
548548
}

TestFoundation/TestNSNumber.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class TestNSNumber : XCTestCase {
3636
("test_stringValue", test_stringValue),
3737
("test_Equals", test_Equals),
3838
("test_boolValue", test_boolValue),
39+
("test_hash", test_hash),
3940
]
4041
}
4142

@@ -1262,4 +1263,26 @@ class TestNSNumber : XCTestCase {
12621263
XCTAssertEqual(NSNumber(value: Int.min + 1).boolValue, true)
12631264
XCTAssertEqual(NSNumber(value: Int(-1)).boolValue, true)
12641265
}
1266+
1267+
func test_hash() {
1268+
// A zero double hashes as zero.
1269+
XCTAssertEqual(NSNumber(value: 0 as Double).hash, 0)
1270+
1271+
// A positive double without fractional part should hash the same as the
1272+
// equivalent 64 bit number.
1273+
XCTAssertEqual(NSNumber(value: 123456 as Double).hash, NSNumber(value: 123456 as Int64).hash)
1274+
1275+
// A negative double without fractional part should hash the same as the
1276+
// equivalent 64 bit number.
1277+
XCTAssertEqual(NSNumber(value: -123456 as Double).hash, NSNumber(value: -123456 as Int64).hash)
1278+
1279+
#if arch(i386) || arch(arm)
1280+
// This test used to fail in 32 bit platforms.
1281+
XCTAssertNotEqual(NSNumber(value: 551048378.24883795 as Double).hash, 0)
1282+
1283+
// Some hashes are correctly zero, though. Like the following which
1284+
// was found by trial and error.
1285+
XCTAssertEqual(NSNumber(value: 1.3819660135 as Double).hash, 0)
1286+
#endif
1287+
}
12651288
}

0 commit comments

Comments
 (0)