@@ -142,6 +142,12 @@ struct Table {
142
142
max_size : usize ,
143
143
}
144
144
145
+ struct StringMarker {
146
+ offset : usize ,
147
+ len : usize ,
148
+ string : Option < Bytes > ,
149
+ }
150
+
145
151
// ===== impl Decoder =====
146
152
147
153
impl Decoder {
@@ -279,10 +285,13 @@ impl Decoder {
279
285
280
286
// First, read the header name
281
287
if table_idx == 0 {
288
+ let old_pos = buf. position ( ) ;
289
+ let name_marker = self . try_decode_string ( buf) ?;
290
+ let value_marker = self . try_decode_string ( buf) ?;
291
+ buf. set_position ( old_pos) ;
282
292
// Read the name as a literal
283
- let name = self . decode_string ( buf) ?;
284
- let value = self . decode_string ( buf) ?;
285
-
293
+ let name = name_marker. consume ( buf) ;
294
+ let value = value_marker. consume ( buf) ;
286
295
Header :: new ( name, value)
287
296
} else {
288
297
let e = self . table . get ( table_idx) ?;
@@ -292,7 +301,11 @@ impl Decoder {
292
301
}
293
302
}
294
303
295
- fn decode_string ( & mut self , buf : & mut Cursor < & mut BytesMut > ) -> Result < Bytes , DecoderError > {
304
+ fn try_decode_string (
305
+ & mut self ,
306
+ buf : & mut Cursor < & mut BytesMut > ,
307
+ ) -> Result < StringMarker , DecoderError > {
308
+ let old_pos = buf. position ( ) ;
296
309
const HUFF_FLAG : u8 = 0b1000_0000 ;
297
310
298
311
// The first bit in the first byte contains the huffman encoded flag.
@@ -309,17 +322,34 @@ impl Decoder {
309
322
return Err ( DecoderError :: NeedMore ( NeedMore :: StringUnderflow ) ) ;
310
323
}
311
324
325
+ let offset = ( buf. position ( ) - old_pos) as usize ;
312
326
if huff {
313
327
let ret = {
314
328
let raw = & buf. chunk ( ) [ ..len] ;
315
- huffman:: decode ( raw, & mut self . buffer ) . map ( BytesMut :: freeze)
329
+ huffman:: decode ( raw, & mut self . buffer ) . map ( |buf| StringMarker {
330
+ offset,
331
+ len,
332
+ string : Some ( BytesMut :: freeze ( buf) ) ,
333
+ } )
316
334
} ;
317
335
318
336
buf. advance ( len) ;
319
- return ret;
337
+ ret
338
+ } else {
339
+ buf. advance ( len) ;
340
+ Ok ( StringMarker {
341
+ offset,
342
+ len,
343
+ string : None ,
344
+ } )
320
345
}
346
+ }
321
347
322
- Ok ( take ( buf, len) )
348
+ fn decode_string ( & mut self , buf : & mut Cursor < & mut BytesMut > ) -> Result < Bytes , DecoderError > {
349
+ let old_pos = buf. position ( ) ;
350
+ let marker = self . try_decode_string ( buf) ?;
351
+ buf. set_position ( old_pos) ;
352
+ Ok ( marker. consume ( buf) )
323
353
}
324
354
}
325
355
@@ -433,6 +463,19 @@ fn take(buf: &mut Cursor<&mut BytesMut>, n: usize) -> Bytes {
433
463
head. freeze ( )
434
464
}
435
465
466
+ impl StringMarker {
467
+ fn consume ( self , buf : & mut Cursor < & mut BytesMut > ) -> Bytes {
468
+ buf. advance ( self . offset ) ;
469
+ match self . string {
470
+ Some ( string) => {
471
+ buf. advance ( self . len ) ;
472
+ string
473
+ }
474
+ None => take ( buf, self . len ) ,
475
+ }
476
+ }
477
+ }
478
+
436
479
fn consume ( buf : & mut Cursor < & mut BytesMut > ) {
437
480
// remove bytes from the internal BytesMut when they have been successfully
438
481
// decoded. This is a more permanent cursor position, which will be
@@ -850,4 +893,48 @@ mod test {
850
893
huffman:: encode ( src, & mut buf) ;
851
894
buf
852
895
}
896
+
897
+ #[ test]
898
+ fn test_decode_continuation_header_with_non_huff_encoded_name ( ) {
899
+ let mut de = Decoder :: new ( 0 ) ;
900
+ let value = huff_encode ( b"bar" ) ;
901
+ let mut buf = BytesMut :: new ( ) ;
902
+ // header name is non_huff encoded
903
+ buf. extend ( & [ 0b01000000 , 0x00 | 3 ] ) ;
904
+ buf. extend ( b"foo" ) ;
905
+ // header value is partial
906
+ buf. extend ( & [ 0x80 | 3 ] ) ;
907
+ buf. extend ( & value[ 0 ..1 ] ) ;
908
+
909
+ let mut res = vec ! [ ] ;
910
+ let e = de
911
+ . decode ( & mut Cursor :: new ( & mut buf) , |h| {
912
+ res. push ( h) ;
913
+ } )
914
+ . unwrap_err ( ) ;
915
+ // decode error because the header value is partial
916
+ assert_eq ! ( e, DecoderError :: NeedMore ( NeedMore :: StringUnderflow ) ) ;
917
+
918
+ // extend buf with the remaining header value
919
+ buf. extend ( & value[ 1 ..] ) ;
920
+ let _ = de
921
+ . decode ( & mut Cursor :: new ( & mut buf) , |h| {
922
+ res. push ( h) ;
923
+ } )
924
+ . unwrap ( ) ;
925
+
926
+ assert_eq ! ( res. len( ) , 1 ) ;
927
+ assert_eq ! ( de. table. size( ) , 0 ) ;
928
+
929
+ match res[ 0 ] {
930
+ Header :: Field {
931
+ ref name,
932
+ ref value,
933
+ } => {
934
+ assert_eq ! ( name, "foo" ) ;
935
+ assert_eq ! ( value, "bar" ) ;
936
+ }
937
+ _ => panic ! ( ) ,
938
+ }
939
+ }
853
940
}
0 commit comments