@@ -82,20 +82,20 @@ internal enum ASN1DERReader {
82
82
83
83
private static func parseItem( _ buffer: inout UnsafeBufferPointer < UInt8 > ) throws -> ASN1 {
84
84
var ( tagValue, itemBuffer) = try parseTagged ( & buffer)
85
- defer {
86
- assert ( itemBuffer. isEmpty)
85
+
86
+ let item = try parseItem ( & itemBuffer, as: tagValue)
87
+
88
+ if !itemBuffer. isEmpty {
89
+ throw ASN1Serialization . Error. invalidTaggedItem
87
90
}
88
91
89
- return try parseItem ( & itemBuffer , as : tagValue )
92
+ return item
90
93
}
91
94
92
95
private static func parseItem(
93
96
_ itemBuffer: inout UnsafeBufferPointer < UInt8 > ,
94
97
as tagValue: ASN1 . AnyTag
95
98
) throws -> ASN1 {
96
- defer {
97
- assert ( itemBuffer. isEmpty)
98
- }
99
99
100
100
guard let tag = ASN1 . Tag ( rawValue: tagValue) else {
101
101
// Check required constructed types
@@ -110,80 +110,87 @@ internal enum ASN1DERReader {
110
110
}
111
111
}
112
112
113
+ let item : ASN1
114
+
113
115
switch tag {
114
116
case . boolean:
115
- return . boolean( try itemBuffer. pop ( ) != 0 )
117
+ item = . boolean( try itemBuffer. pop ( ) != 0 )
116
118
117
119
case . integer:
118
- return . integer( try parseInt ( & itemBuffer) )
120
+ item = . integer( try parseInt ( & itemBuffer) )
119
121
120
122
case . bitString:
121
123
let unusedBits = try itemBuffer. pop ( )
122
124
let data = Data ( try itemBuffer. popAll ( ) )
123
- return . bitString( ( data. count * 8 ) - Int( unusedBits) , data)
125
+ item = . bitString( ( data. count * 8 ) - Int( unusedBits) , data)
124
126
125
127
case . octetString:
126
- return . octetString( Data ( try itemBuffer. popAll ( ) ) )
128
+ item = . octetString( Data ( try itemBuffer. popAll ( ) ) )
127
129
128
130
case . null:
129
- return . null
131
+ item = . null
130
132
131
133
case . objectIdentifier:
132
- return . objectIdentifier( try parseOID ( & itemBuffer) )
134
+ item = . objectIdentifier( try parseOID ( & itemBuffer) )
133
135
134
136
case . real:
135
- return . real( try parseReal ( & itemBuffer) )
137
+ item = . real( try parseReal ( & itemBuffer) )
136
138
137
139
case . utf8String:
138
- return . utf8String( try parseString ( & itemBuffer, encoding: . utf8) )
140
+ item = . utf8String( try parseString ( & itemBuffer, encoding: . utf8) )
139
141
140
142
case . numericString:
141
- return . numericString( try parseString ( & itemBuffer, encoding: . ascii) )
143
+ item = . numericString( try parseString ( & itemBuffer, encoding: . ascii) )
142
144
143
145
case . printableString:
144
- return . printableString( try parseString ( & itemBuffer, encoding: . ascii) )
146
+ item = . printableString( try parseString ( & itemBuffer, encoding: . ascii) )
145
147
146
148
case . teletexString:
147
- return . teletexString( try parseString ( & itemBuffer, encoding: . ascii) )
149
+ item = . teletexString( try parseString ( & itemBuffer, encoding: . ascii) )
148
150
149
151
case . videotexString:
150
- return . videotexString( try parseString ( & itemBuffer, encoding: . ascii) )
152
+ item = . videotexString( try parseString ( & itemBuffer, encoding: . ascii) )
151
153
152
154
case . ia5String:
153
- return . ia5String( try parseString ( & itemBuffer, encoding: . ascii) )
155
+ item = . ia5String( try parseString ( & itemBuffer, encoding: . ascii) )
154
156
155
157
case . utcTime:
156
- return . utcTime( try parseTime ( & itemBuffer, formatter: utcFormatter) )
158
+ item = . utcTime( try parseTime ( & itemBuffer, formatter: utcFormatter) )
157
159
158
160
case . generalizedTime:
159
- return . generalizedTime( try parseTime ( & itemBuffer, formatter: generalizedFormatter) )
161
+ item = . generalizedTime( try parseTime ( & itemBuffer, formatter: generalizedFormatter) )
160
162
161
163
case . graphicString:
162
- return . graphicString( try parseString ( & itemBuffer, encoding: . ascii) )
164
+ item = . graphicString( try parseString ( & itemBuffer, encoding: . ascii) )
163
165
164
166
case . visibleString:
165
- return . visibleString( try parseString ( & itemBuffer, encoding: . ascii) )
167
+ item = . visibleString( try parseString ( & itemBuffer, encoding: . ascii) )
166
168
167
169
case . generalString:
168
- return . generalString( try parseString ( & itemBuffer, encoding: . ascii) )
170
+ item = . generalString( try parseString ( & itemBuffer, encoding: . ascii) )
169
171
170
172
case . universalString:
171
- return . universalString( try parseString ( & itemBuffer, encoding: . ascii) )
173
+ item = . universalString( try parseString ( & itemBuffer, encoding: . ascii) )
172
174
173
175
case . characterString:
174
- return . characterString( try parseString ( & itemBuffer, encoding: . ascii) )
176
+ item = . characterString( try parseString ( & itemBuffer, encoding: . ascii) )
175
177
176
178
case . bmpString:
177
- return . bmpString( try parseString ( & itemBuffer, encoding: . ascii) )
179
+ item = . bmpString( try parseString ( & itemBuffer, encoding: . ascii) )
178
180
179
181
case . sequence, . set:
180
182
throw ASN1Serialization . Error. nonConstructedCollection
181
183
182
184
case . objectDescriptor, . external, . enumerated, . embedded, . relativeOID:
183
185
// Default to saving tagged version
184
- return . tagged( tag. rawValue, Data ( try itemBuffer. popAll ( ) ) )
186
+ item = . tagged( tag. rawValue, Data ( try itemBuffer. popAll ( ) ) )
187
+ }
188
+
189
+ if !itemBuffer. isEmpty {
190
+ throw ASN1Serialization . Error. invalidTaggedItem
185
191
}
186
192
193
+ return item
187
194
}
188
195
189
196
private static func parseTime(
@@ -213,7 +220,7 @@ internal enum ASN1DERReader {
213
220
private static func parseReal( _ buffer: inout UnsafeBufferPointer < UInt8 > ) throws -> Decimal {
214
221
let lead = try buffer. pop ( )
215
222
if lead & 0x40 == 0x40 {
216
- return lead & 0x1 == 0 ? Decimal ( Double . infinity ) : Decimal ( - Double . infinity )
223
+ throw ASN1Serialization . Error . unsupportedReal
217
224
}
218
225
else if lead & 0xC0 == 0 {
219
226
let bytes = try buffer. popAll ( )
@@ -303,7 +310,20 @@ internal enum ASN1DERReader {
303
310
}
304
311
305
312
for _ in 0 ..< numBytes {
306
- length = ( length * 0x100 ) + Int( try buffer. pop ( ) )
313
+
314
+ let newLength = ( length &* 0x100 ) &+ Int ( try buffer. pop ( ) )
315
+
316
+ // Check for overflow
317
+ if newLength < length {
318
+ throw ASN1Serialization . Error. lengthOverflow
319
+ }
320
+
321
+ // Check avaiable data
322
+ if newLength > buffer. count {
323
+ throw ASN1Serialization . Error. unexpectedEOF
324
+ }
325
+
326
+ length = newLength
307
327
}
308
328
309
329
return length
0 commit comments