From 9500471ede62d8158191193dfbe333e4f3ba3ab8 Mon Sep 17 00:00:00 2001 From: Xiaodi Wu Date: Sun, 5 Aug 2018 18:58:03 -0400 Subject: [PATCH] [JSONSerialization] Use Int64 and UInt64 for integer parsing --- Foundation/JSONSerialization.swift | 29 +++++++++++++++------- TestFoundation/TestJSONSerialization.swift | 4 ++- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/Foundation/JSONSerialization.swift b/Foundation/JSONSerialization.swift index a54c5c75f0..e2012781f5 100644 --- a/Foundation/JSONSerialization.swift +++ b/Foundation/JSONSerialization.swift @@ -826,22 +826,33 @@ private struct JSONReader { let temp_buffer_size = 64 var temp_buffer = [Int8](repeating: 0, count: temp_buffer_size) return temp_buffer.withUnsafeMutableBufferPointer { (buffer: inout UnsafeMutableBufferPointer) -> (Any, IndexDistance)? in - memcpy(buffer.baseAddress!, address, min(count, temp_buffer_size - 1)) // ensure null termination - + memcpy(buffer.baseAddress!, address, min(count, temp_buffer_size - 1)) // Ensure null termination + let startPointer = buffer.baseAddress! - let intEndPointer = UnsafeMutablePointer?>.allocate(capacity: 1) - defer { intEndPointer.deallocate() } let doubleEndPointer = UnsafeMutablePointer?>.allocate(capacity: 1) defer { doubleEndPointer.deallocate() } - let intResult = strtol(startPointer, intEndPointer, 10) - let intDistance = startPointer.distance(to: intEndPointer[0]!) let doubleResult = strtod(startPointer, doubleEndPointer) let doubleDistance = startPointer.distance(to: doubleEndPointer[0]!) + guard doubleDistance > 0 else { + return nil + } - guard doubleDistance > 0 else { return nil } - if intDistance == doubleDistance { - return (NSNumber(value: intResult), intDistance) + let int64EndPointer = UnsafeMutablePointer?>.allocate(capacity: 1) + defer { int64EndPointer.deallocate() } + let int64Result = strtoll(startPointer, int64EndPointer, 10) + let int64Distance = startPointer.distance(to: int64EndPointer[0]!) + if int64Distance == doubleDistance { + return (NSNumber(value: int64Result), int64Distance) } + + let uint64EndPointer = UnsafeMutablePointer?>.allocate(capacity: 1) + defer { uint64EndPointer.deallocate() } + let uint64Result = strtoull(startPointer, uint64EndPointer, 10) + let uint64Distance = startPointer.distance(to: uint64EndPointer[0]!) + if uint64Distance == doubleDistance { + return (NSNumber(value: uint64Result), uint64Distance) + } + return (NSNumber(value: doubleResult), doubleDistance) } } diff --git a/TestFoundation/TestJSONSerialization.swift b/TestFoundation/TestJSONSerialization.swift index 220c253143..268e046c53 100644 --- a/TestFoundation/TestJSONSerialization.swift +++ b/TestFoundation/TestJSONSerialization.swift @@ -487,7 +487,7 @@ extension TestJSONSerialization { //MARK: - Number parsing func deserialize_numbers(objectType: ObjectType) { - let subject = "[1, -1, 1.3, -1.3, 1e3, 1E-3, 10]" + let subject = "[1, -1, 1.3, -1.3, 1e3, 1E-3, 10, \(UInt64.max)]" do { for encoding in supportedEncodings { @@ -504,6 +504,8 @@ extension TestJSONSerialization { XCTAssertEqual(result?[5] as? Double, 0.001) XCTAssertEqual(result?[6] as? Int, 10) XCTAssertEqual(result?[6] as? Double, 10.0) + XCTAssertEqual(result?[7] as? Int64, nil) + XCTAssertEqual(result?[7] as? UInt64, UInt64.max) } } catch { XCTFail("Unexpected error: \(error)")