@@ -142,6 +142,12 @@ struct Table {
142142 max_size : usize ,
143143}
144144
145+ struct StringMarker {
146+ offset : usize ,
147+ len : usize ,
148+ string : Option < Bytes > ,
149+ }
150+
145151// ===== impl Decoder =====
146152
147153impl Decoder {
@@ -279,10 +285,13 @@ impl Decoder {
279285
280286 // First, read the header name
281287 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) ;
282292 // 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) ;
286295 Header :: new ( name, value)
287296 } else {
288297 let e = self . table . get ( table_idx) ?;
@@ -292,7 +301,11 @@ impl Decoder {
292301 }
293302 }
294303
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 ( ) ;
296309 const HUFF_FLAG : u8 = 0b1000_0000 ;
297310
298311 // The first bit in the first byte contains the huffman encoded flag.
@@ -309,17 +322,34 @@ impl Decoder {
309322 return Err ( DecoderError :: NeedMore ( NeedMore :: StringUnderflow ) ) ;
310323 }
311324
325+ let offset = ( buf. position ( ) - old_pos) as usize ;
312326 if huff {
313327 let ret = {
314328 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+ } )
316334 } ;
317335
318336 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+ } )
320345 }
346+ }
321347
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) )
323353 }
324354}
325355
@@ -433,6 +463,19 @@ fn take(buf: &mut Cursor<&mut BytesMut>, n: usize) -> Bytes {
433463 head. freeze ( )
434464}
435465
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+
436479fn consume ( buf : & mut Cursor < & mut BytesMut > ) {
437480 // remove bytes from the internal BytesMut when they have been successfully
438481 // decoded. This is a more permanent cursor position, which will be
@@ -850,4 +893,48 @@ mod test {
850893 huffman:: encode ( src, & mut buf) ;
851894 buf
852895 }
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+ }
853940}
0 commit comments