mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[stdlib] Prevent type coercion from Bool to numerical types when decoding JSON and plist
JSONEncoder and PropertyListEncoder both use NSNumber to box Bool values. An encoded Bool can be coerced to any numerical type during decoding because (false as NSNumber).intValue == 0. As a remedy, all of the unbox(_:as:) methods of _JSONDecoder and _PlistDecoder for numerical types include a check that the value is not identical to either kCFBooleanTrue or kCFBooleanFalse, and throw a DecodingError._typeMismatch(at:expectation:) if this check fails.
This commit is contained in:
@@ -1767,7 +1767,7 @@ extension _JSONDecoder {
|
||||
fileprivate func unbox(_ value: Any, as type: Int.Type) throws -> Int? {
|
||||
guard !(value is NSNull) else { return nil }
|
||||
|
||||
guard let number = value as? NSNumber else {
|
||||
guard let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse else {
|
||||
throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
|
||||
}
|
||||
|
||||
@@ -1782,7 +1782,7 @@ extension _JSONDecoder {
|
||||
fileprivate func unbox(_ value: Any, as type: Int8.Type) throws -> Int8? {
|
||||
guard !(value is NSNull) else { return nil }
|
||||
|
||||
guard let number = value as? NSNumber else {
|
||||
guard let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse else {
|
||||
throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
|
||||
}
|
||||
|
||||
@@ -1797,7 +1797,7 @@ extension _JSONDecoder {
|
||||
fileprivate func unbox(_ value: Any, as type: Int16.Type) throws -> Int16? {
|
||||
guard !(value is NSNull) else { return nil }
|
||||
|
||||
guard let number = value as? NSNumber else {
|
||||
guard let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse else {
|
||||
throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
|
||||
}
|
||||
|
||||
@@ -1812,7 +1812,7 @@ extension _JSONDecoder {
|
||||
fileprivate func unbox(_ value: Any, as type: Int32.Type) throws -> Int32? {
|
||||
guard !(value is NSNull) else { return nil }
|
||||
|
||||
guard let number = value as? NSNumber else {
|
||||
guard let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse else {
|
||||
throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
|
||||
}
|
||||
|
||||
@@ -1827,7 +1827,7 @@ extension _JSONDecoder {
|
||||
fileprivate func unbox(_ value: Any, as type: Int64.Type) throws -> Int64? {
|
||||
guard !(value is NSNull) else { return nil }
|
||||
|
||||
guard let number = value as? NSNumber else {
|
||||
guard let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse else {
|
||||
throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
|
||||
}
|
||||
|
||||
@@ -1842,7 +1842,7 @@ extension _JSONDecoder {
|
||||
fileprivate func unbox(_ value: Any, as type: UInt.Type) throws -> UInt? {
|
||||
guard !(value is NSNull) else { return nil }
|
||||
|
||||
guard let number = value as? NSNumber else {
|
||||
guard let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse else {
|
||||
throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
|
||||
}
|
||||
|
||||
@@ -1857,7 +1857,7 @@ extension _JSONDecoder {
|
||||
fileprivate func unbox(_ value: Any, as type: UInt8.Type) throws -> UInt8? {
|
||||
guard !(value is NSNull) else { return nil }
|
||||
|
||||
guard let number = value as? NSNumber else {
|
||||
guard let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse else {
|
||||
throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
|
||||
}
|
||||
|
||||
@@ -1872,7 +1872,7 @@ extension _JSONDecoder {
|
||||
fileprivate func unbox(_ value: Any, as type: UInt16.Type) throws -> UInt16? {
|
||||
guard !(value is NSNull) else { return nil }
|
||||
|
||||
guard let number = value as? NSNumber else {
|
||||
guard let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse else {
|
||||
throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
|
||||
}
|
||||
|
||||
@@ -1887,7 +1887,7 @@ extension _JSONDecoder {
|
||||
fileprivate func unbox(_ value: Any, as type: UInt32.Type) throws -> UInt32? {
|
||||
guard !(value is NSNull) else { return nil }
|
||||
|
||||
guard let number = value as? NSNumber else {
|
||||
guard let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse else {
|
||||
throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
|
||||
}
|
||||
|
||||
@@ -1902,7 +1902,7 @@ extension _JSONDecoder {
|
||||
fileprivate func unbox(_ value: Any, as type: UInt64.Type) throws -> UInt64? {
|
||||
guard !(value is NSNull) else { return nil }
|
||||
|
||||
guard let number = value as? NSNumber else {
|
||||
guard let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse else {
|
||||
throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
|
||||
}
|
||||
|
||||
@@ -1917,7 +1917,7 @@ extension _JSONDecoder {
|
||||
fileprivate func unbox(_ value: Any, as type: Float.Type) throws -> Float? {
|
||||
guard !(value is NSNull) else { return nil }
|
||||
|
||||
if let number = value as? NSNumber {
|
||||
if let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse {
|
||||
// We are willing to return a Float by losing precision:
|
||||
// * If the original value was integral,
|
||||
// * and the integral value was > Float.greatestFiniteMagnitude, we will fail
|
||||
@@ -1963,7 +1963,7 @@ extension _JSONDecoder {
|
||||
fileprivate func unbox(_ value: Any, as type: Double.Type) throws -> Double? {
|
||||
guard !(value is NSNull) else { return nil }
|
||||
|
||||
if let number = value as? NSNumber {
|
||||
if let number = value as? NSNumber, number !== kCFBooleanTrue, number !== kCFBooleanFalse {
|
||||
// We are always willing to return the number as a Double:
|
||||
// * If the original value was integral, it is guaranteed to fit in a Double; we are willing to lose precision past 2^53 if you encoded a UInt64 but requested a Double
|
||||
// * If it was a Float or Double, you will get back the precise value
|
||||
|
||||
Reference in New Issue
Block a user