Skip to content

Commit 3ca41d3

Browse files
committed
Fix a crash in BSON that could happen when converting a Double into an Int of your choosing with the Double being too large
1 parent fca6470 commit 3ca41d3

File tree

2 files changed

+38
-4
lines changed

2 files changed

+38
-4
lines changed

Sources/BSON/Codable/Decoding/BSONDecoder.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,13 @@ extension BSONDecoderSettings.IntegerDecodingStrategy {
138138
case (let int as Int, _):
139139
return try int.convert(to: I.self)
140140
case (let double as Double, .roundingAnyNumber), (let double as Double, .adaptive):
141+
guard
142+
double >= Double(I.min),
143+
double <= Double(I.max)
144+
else {
145+
throw DecodingError.typeMismatch(Double.self, .init(codingPath: [], debugDescription: "The IntegerDecodingStrategy is adaptive, but the Double could not be converted to \(I.self)"))
146+
}
147+
141148
return I(double)
142149
case (let string as String, .adaptive):
143150
guard let int = I(string) else {
@@ -177,6 +184,13 @@ extension BSONDecoderSettings.IntegerDecodingStrategy {
177184
case (.int64, let int as Int), (.adaptive, let int as Int), (.anyInteger, let int as Int), (.roundingAnyNumber, let int as Int):
178185
return try int.convert(to: I.self)
179186
case (.roundingAnyNumber, let double as Double), (.adaptive, let double as Double):
187+
guard
188+
double >= Double(I.min),
189+
double <= Double(I.max)
190+
else {
191+
throw DecodingError.typeMismatch(Double.self, .init(codingPath: [], debugDescription: "The IntegerDecodingStrategy is adaptive, but the Double could not be converted to \(I.self)"))
192+
}
193+
180194
return I(double)
181195
case (.custom(let strategy), _):
182196
guard let value: I = try strategy(key, value) else {

Sources/BSON/Codable/Decoding/Fast/FastBSONDecoder.swift

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,18 @@ struct _FastKeyedContainer<Key: CodingKey>: KeyedDecodingContainerProtocol {
116116
}
117117

118118
return F(int)
119+
case .double:
120+
guard
121+
let double = document.storage.getDouble(at: offset),
122+
double >= Double(F.min),
123+
double <= Double(F.max)
124+
else {
125+
throw BSONValueNotFound(type: F.self, path: codingPath.map(\.stringValue) + [key.stringValue])
126+
}
127+
128+
return F(double)
119129
default:
120-
throw BSONValueNotFound(type: F.self, path: codingPath.map(\.stringValue))
130+
throw BSONValueNotFound(type: F.self, path: codingPath.map(\.stringValue) + [key.stringValue])
121131
}
122132
}
123133

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

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

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

157167
return double
@@ -690,6 +700,16 @@ struct _FastUnkeyedContainer: UnkeyedDecodingContainer {
690700

691701
currentIndex += 1
692702
return F(int)
703+
case .double:
704+
guard
705+
let double = document.storage.getDouble(at: offset),
706+
double >= Double(F.min),
707+
double <= Double(F.max)
708+
else {
709+
throw BSONValueNotFound(type: F.self, path: codingPath.map(\.stringValue))
710+
}
711+
712+
return F(double)
693713
default:
694714
throw BSONValueNotFound(type: F.self, path: codingPath.map(\.stringValue))
695715
}

0 commit comments

Comments
 (0)