@@ -15,6 +15,7 @@ use bytes::BufMut;
15
15
use ProtobufResult ;
16
16
use ProtobufError ;
17
17
use error:: WireError ;
18
+ use stream:: READ_RAW_BYTES_MAX_ALLOC ;
18
19
19
20
20
21
// If an input stream is constructed with a `Read`, we create a
@@ -221,6 +222,61 @@ impl<'ignore> BufReadIter<'ignore> {
221
222
Ok ( r)
222
223
}
223
224
225
+ /// Read at most `max` bytes, append to `Vec`.
226
+ ///
227
+ /// Returns 0 when EOF or limit reached.
228
+ fn read_to_vec ( & mut self , vec : & mut Vec < u8 > , max : usize ) -> ProtobufResult < usize > {
229
+ let rem = self . fill_buf ( ) ?;
230
+
231
+ let len = cmp:: min ( rem. len ( ) , max) ;
232
+ vec. extend_from_slice ( & rem[ ..len] ) ;
233
+ self . pos_within_buf += len;
234
+ Ok ( len)
235
+ }
236
+
237
+ /// Read exact number of bytes into `Vec`.
238
+ ///
239
+ /// `Vec` is cleared in the beginning.
240
+ pub fn read_exact_to_vec ( & mut self , count : usize , target : & mut Vec < u8 > ) -> ProtobufResult < ( ) > {
241
+ // TODO: also do some limits when reading from unlimited source
242
+ if count as u64 > self . bytes_until_limit ( ) {
243
+ return Err ( ProtobufError :: WireError ( WireError :: TruncatedMessage ) ) ;
244
+ }
245
+
246
+ target. clear ( ) ;
247
+
248
+ if count >= READ_RAW_BYTES_MAX_ALLOC && count > target. capacity ( ) {
249
+ // avoid calling `reserve` on buf with very large buffer: could be a malformed message
250
+
251
+ target. reserve ( READ_RAW_BYTES_MAX_ALLOC ) ;
252
+
253
+ while target. len ( ) < count {
254
+ if count - target. len ( ) <= target. len ( ) {
255
+ target. reserve_exact ( count - target. len ( ) ) ;
256
+ } else {
257
+ target. reserve ( 1 ) ;
258
+ }
259
+
260
+ let max = cmp:: min ( target. capacity ( ) - target. len ( ) , count - target. len ( ) ) ;
261
+ let read = self . read_to_vec ( target, max) ?;
262
+ if read == 0 {
263
+ return Err ( ProtobufError :: WireError ( WireError :: TruncatedMessage ) ) ;
264
+ }
265
+ }
266
+ } else {
267
+ target. reserve_exact ( count) ;
268
+
269
+ unsafe {
270
+ self . read_exact ( & mut target. get_unchecked_mut ( ..count) ) ?;
271
+ target. set_len ( count) ;
272
+ }
273
+ }
274
+
275
+ debug_assert_eq ! ( count, target. len( ) ) ;
276
+
277
+ Ok ( ( ) )
278
+ }
279
+
224
280
#[ cfg( feature = "bytes" ) ]
225
281
pub fn read_exact_bytes ( & mut self , len : usize ) -> ProtobufResult < Bytes > {
226
282
if let InputSource :: Bytes ( bytes) = self . input_source {
@@ -231,15 +287,21 @@ impl<'ignore> BufReadIter<'ignore> {
231
287
self . pos_within_buf += len;
232
288
Ok ( r)
233
289
} else {
234
- let mut r = BytesMut :: with_capacity ( len) ;
235
- unsafe {
236
- {
237
- let mut buf = & mut r. bytes_mut ( ) [ ..len] ;
290
+ if len >= READ_RAW_BYTES_MAX_ALLOC {
291
+ // We cannot trust `len` because protobuf message could be malformed.
292
+ // Reading should not result in OOM when allocating a buffer.
293
+ let mut v = Vec :: new ( ) ;
294
+ self . read_exact_to_vec ( len, & mut v) ?;
295
+ Ok ( Bytes :: from ( v) )
296
+ } else {
297
+ let mut r = BytesMut :: with_capacity ( len) ;
298
+ unsafe {
299
+ let buf = & mut r. bytes_mut ( ) [ ..len] ;
238
300
self . read_exact ( buf) ?;
301
+ r. advance_mut ( len) ;
239
302
}
240
- r . advance_mut ( len ) ;
303
+ Ok ( r . freeze ( ) )
241
304
}
242
- Ok ( r. freeze ( ) )
243
305
}
244
306
}
245
307
0 commit comments