Skip to content

Commit

Permalink
Fix a crash in BSON that could happen when converting a Double into a…
Browse files Browse the repository at this point in the history
…n Int of your choosing with the Double being too large
  • Loading branch information
Joannis committed Mar 15, 2023
1 parent fca6470 commit 3ca41d3
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 4 deletions.
14 changes: 14 additions & 0 deletions Sources/BSON/Codable/Decoding/BSONDecoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,13 @@ extension BSONDecoderSettings.IntegerDecodingStrategy {
case (let int as Int, _):
return try int.convert(to: I.self)
case (let double as Double, .roundingAnyNumber), (let double as Double, .adaptive):
guard
double >= Double(I.min),
double <= Double(I.max)
else {
throw DecodingError.typeMismatch(Double.self, .init(codingPath: [], debugDescription: "The IntegerDecodingStrategy is adaptive, but the Double could not be converted to \(I.self)"))
}

return I(double)
case (let string as String, .adaptive):
guard let int = I(string) else {
Expand Down Expand Up @@ -177,6 +184,13 @@ extension BSONDecoderSettings.IntegerDecodingStrategy {
case (.int64, let int as Int), (.adaptive, let int as Int), (.anyInteger, let int as Int), (.roundingAnyNumber, let int as Int):
return try int.convert(to: I.self)
case (.roundingAnyNumber, let double as Double), (.adaptive, let double as Double):
guard
double >= Double(I.min),
double <= Double(I.max)
else {
throw DecodingError.typeMismatch(Double.self, .init(codingPath: [], debugDescription: "The IntegerDecodingStrategy is adaptive, but the Double could not be converted to \(I.self)"))
}

return I(double)
case (.custom(let strategy), _):
guard let value: I = try strategy(key, value) else {
Expand Down
28 changes: 24 additions & 4 deletions Sources/BSON/Codable/Decoding/Fast/FastBSONDecoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,18 @@ struct _FastKeyedContainer<Key: CodingKey>: KeyedDecodingContainerProtocol {
}

return F(int)
case .double:
guard
let double = document.storage.getDouble(at: offset),
double >= Double(F.min),
double <= Double(F.max)
else {
throw BSONValueNotFound(type: F.self, path: codingPath.map(\.stringValue) + [key.stringValue])
}

return F(double)
default:
throw BSONValueNotFound(type: F.self, path: codingPath.map(\.stringValue))
throw BSONValueNotFound(type: F.self, path: codingPath.map(\.stringValue) + [key.stringValue])
}
}

Expand All @@ -127,7 +137,7 @@ struct _FastKeyedContainer<Key: CodingKey>: KeyedDecodingContainerProtocol {
type == .boolean,
let int: UInt8 = document.storage.getInteger(at: offset, endianness: .little)
else {
throw BSONValueNotFound(type: Bool.self, path: codingPath.map(\.stringValue))
throw BSONValueNotFound(type: Bool.self, path: codingPath.map(\.stringValue) + [key.stringValue])
}

return int == 0x01
Expand All @@ -139,7 +149,7 @@ struct _FastKeyedContainer<Key: CodingKey>: KeyedDecodingContainerProtocol {
type == .string,
let string = document.storage.getBSONString(at: offset)
else {
throw BSONValueNotFound(type: String.self, path: codingPath.map(\.stringValue))
throw BSONValueNotFound(type: String.self, path: codingPath.map(\.stringValue) + [key.stringValue])
}

return string
Expand All @@ -151,7 +161,7 @@ struct _FastKeyedContainer<Key: CodingKey>: KeyedDecodingContainerProtocol {
type == .double,
let double = document.storage.getDouble(at: offset)
else {
throw BSONValueNotFound(type: Double.self, path: codingPath.map(\.stringValue))
throw BSONValueNotFound(type: String.self, path: codingPath.map(\.stringValue) + [key.stringValue])
}

return double
Expand Down Expand Up @@ -690,6 +700,16 @@ struct _FastUnkeyedContainer: UnkeyedDecodingContainer {

currentIndex += 1
return F(int)
case .double:
guard
let double = document.storage.getDouble(at: offset),
double >= Double(F.min),
double <= Double(F.max)
else {
throw BSONValueNotFound(type: F.self, path: codingPath.map(\.stringValue))
}

return F(double)
default:
throw BSONValueNotFound(type: F.self, path: codingPath.map(\.stringValue))
}
Expand Down

0 comments on commit 3ca41d3

Please sign in to comment.