Skip to content

Commit b541491

Browse files
authored
Merge pull request from GHSA-239c-6cv2-wwx8
[5.6] Fix an issue in JSONDecoder where the decoder uses mismatches accessors on NSNumber for numeric conversion.
2 parents e82400e + 3034c9c commit b541491

File tree

2 files changed

+66
-5
lines changed

2 files changed

+66
-5
lines changed

Sources/Foundation/JSONDecoder.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -454,30 +454,30 @@ extension JSONDecoderImpl: Decoder {
454454
return nsNumber.uint8Value as! T
455455
}
456456
if type == Int8.self, NSNumber(value: nsNumber.int8Value) == nsNumber {
457-
return nsNumber.uint8Value as! T
457+
return nsNumber.int8Value as! T
458458
}
459459
if type == UInt16.self, NSNumber(value: nsNumber.uint16Value) == nsNumber {
460460
return nsNumber.uint16Value as! T
461461
}
462462
if type == Int16.self, NSNumber(value: nsNumber.int16Value) == nsNumber {
463-
return nsNumber.uint16Value as! T
463+
return nsNumber.int16Value as! T
464464
}
465465
if type == UInt32.self, NSNumber(value: nsNumber.uint32Value) == nsNumber {
466466
return nsNumber.uint32Value as! T
467467
}
468468
if type == Int32.self, NSNumber(value: nsNumber.int32Value) == nsNumber {
469-
return nsNumber.uint32Value as! T
469+
return nsNumber.int32Value as! T
470470
}
471471
if type == UInt64.self, NSNumber(value: nsNumber.uint64Value) == nsNumber {
472472
return nsNumber.uint64Value as! T
473473
}
474474
if type == Int64.self, NSNumber(value: nsNumber.int64Value) == nsNumber {
475-
return nsNumber.uint64Value as! T
475+
return nsNumber.int64Value as! T
476476
}
477477
if type == UInt.self, NSNumber(value: nsNumber.uintValue) == nsNumber {
478478
return nsNumber.uintValue as! T
479479
}
480-
if type == Int.self, NSNumber(value: nsNumber.uintValue) == nsNumber {
480+
if type == Int.self, NSNumber(value: nsNumber.intValue) == nsNumber {
481481
return nsNumber.intValue as! T
482482
}
483483
}

Tests/Foundation/Tests/TestJSONEncoder.swift

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,66 @@ class TestJSONEncoder : XCTestCase {
656656
}
657657
}
658658

659+
func test_encodeDecodeNumericTypesBaseline() throws {
660+
struct NumericTypesStruct: Codable, Equatable {
661+
let int8Value: Int8
662+
let uint8Value: UInt8
663+
let int16Value: Int16
664+
let uint16Value: UInt16
665+
let int32Value: Int32
666+
let uint32Value: UInt32
667+
let int64Value: Int64
668+
let intValue: Int
669+
let uintValue: UInt
670+
let uint64Value: UInt64
671+
let floatValue: Float
672+
let doubleValue: Double
673+
let decimalValue: Decimal
674+
}
675+
676+
let source = NumericTypesStruct(
677+
int8Value: -12,
678+
uint8Value: 34,
679+
int16Value: -5678,
680+
uint16Value: 9011,
681+
int32Value: -12141516,
682+
uint32Value: 17181920,
683+
int64Value: -21222324252627,
684+
intValue: -2829303132,
685+
uintValue: 33343536,
686+
uint64Value: 373839404142,
687+
floatValue: 1.234,
688+
doubleValue: 5.101520,
689+
decimalValue: Decimal(10))
690+
691+
let data = try JSONEncoder().encode(source)
692+
let destination = try JSONDecoder().decode(NumericTypesStruct.self, from: data)
693+
XCTAssertEqual(source, destination)
694+
695+
// Ensure that if a value is expressed as a floating point number, it casts correctly into the underlying type.
696+
697+
let json = """
698+
{
699+
"int8Value": -12.0,
700+
"uint8Value": 34.0,
701+
"int16Value": -5678.0,
702+
"uint16Value": 9011.0,
703+
"int32Value": -12141516.0,
704+
"uint32Value": 17181920.0,
705+
"int64Value": -21222324252627.0,
706+
"intValue": -2829303132.0,
707+
"uintValue": 33343536.0,
708+
"uint64Value": 373839404142.0,
709+
"floatValue": 1.234,
710+
"doubleValue": 5.101520,
711+
"decimalValue": 10.0
712+
}
713+
"""
714+
715+
let destination2 = try JSONDecoder().decode(NumericTypesStruct.self, from: Data(json.utf8))
716+
XCTAssertEqual(source, destination2)
717+
}
718+
659719
func test_numericLimits() {
660720
struct DataStruct: Codable {
661721
let int8Value: Int8?
@@ -1479,6 +1539,7 @@ extension TestJSONEncoder {
14791539
("test_encodingCustomDataEmpty", test_encodingCustomDataEmpty),
14801540
("test_encodingNonConformingFloats", test_encodingNonConformingFloats),
14811541
("test_encodingNonConformingFloatStrings", test_encodingNonConformingFloatStrings),
1542+
("test_encodeDecodeNumericTypesBaseline", test_encodeDecodeNumericTypesBaseline),
14821543
("test_nestedContainerCodingPaths", test_nestedContainerCodingPaths),
14831544
("test_superEncoderCodingPaths", test_superEncoderCodingPaths),
14841545
("test_codingOfBool", test_codingOfBool),

0 commit comments

Comments
 (0)