1use std::error::Error as StdError;
2use std::fmt;
3use std::io;
4use std::task::{Context, Poll};
5
6use bytes::{BufMut, Bytes, BytesMut};
7use futures_core::ready;
8use http::{HeaderMap, HeaderName, HeaderValue};
9use http_body::Frame;
10
11use super::io::MemRead;
12use super::role::DEFAULT_MAX_HEADERS;
13use super::DecodedLength;
14
15use self::Kind::{Chunked, Eof, Length};
16
17const CHUNKED_EXTENSIONS_LIMIT: u64 = 1024 * 16;
21
22const TRAILER_LIMIT: usize = 1024 * 16;
26
27#[derive(Clone, PartialEq)]
32pub(crate) struct Decoder {
33 kind: Kind,
34}
35
36#[derive(Debug, Clone, PartialEq)]
37enum Kind {
38 Length(u64),
40 Chunked {
42 state: ChunkedState,
43 chunk_len: u64,
44 extensions_cnt: u64,
45 trailers_buf: Option<BytesMut>,
46 trailers_cnt: usize,
47 h1_max_headers: Option<usize>,
48 h1_max_header_size: Option<usize>,
49 },
50 Eof(bool),
67}
68
69#[derive(Debug, PartialEq, Clone, Copy)]
70enum ChunkedState {
71 Start,
72 Size,
73 SizeLws,
74 Extension,
75 SizeLf,
76 Body,
77 BodyCr,
78 BodyLf,
79 Trailer,
80 TrailerLf,
81 EndCr,
82 EndLf,
83 End,
84}
85
86impl Decoder {
87 pub(crate) fn length(x: u64) -> Decoder {
90 Decoder {
91 kind: Kind::Length(x),
92 }
93 }
94
95 pub(crate) fn chunked(
96 h1_max_headers: Option<usize>,
97 h1_max_header_size: Option<usize>,
98 ) -> Decoder {
99 Decoder {
100 kind: Kind::Chunked {
101 state: ChunkedState::new(),
102 chunk_len: 0,
103 extensions_cnt: 0,
104 trailers_buf: None,
105 trailers_cnt: 0,
106 h1_max_headers,
107 h1_max_header_size,
108 },
109 }
110 }
111
112 pub(crate) fn eof() -> Decoder {
113 Decoder {
114 kind: Kind::Eof(false),
115 }
116 }
117
118 pub(super) fn new(
119 len: DecodedLength,
120 h1_max_headers: Option<usize>,
121 h1_max_header_size: Option<usize>,
122 ) -> Self {
123 match len {
124 DecodedLength::CHUNKED => Decoder::chunked(h1_max_headers, h1_max_header_size),
125 DecodedLength::CLOSE_DELIMITED => Decoder::eof(),
126 length => Decoder::length(length.danger_len()),
127 }
128 }
129
130 pub(crate) fn is_eof(&self) -> bool {
133 matches!(
134 self.kind,
135 Length(0)
136 | Chunked {
137 state: ChunkedState::End,
138 ..
139 }
140 | Eof(true)
141 )
142 }
143
144 pub(crate) fn decode<R: MemRead>(
145 &mut self,
146 cx: &mut Context<'_>,
147 body: &mut R,
148 ) -> Poll<Result<Frame<Bytes>, io::Error>> {
149 trace!("decode; state={:?}", self.kind);
150 match self.kind {
151 Length(ref mut remaining) => {
152 if *remaining == 0 {
153 Poll::Ready(Ok(Frame::data(Bytes::new())))
154 } else {
155 let to_read = usize::try_from(*remaining).unwrap_or(usize::MAX);
156 let buf = ready!(body.read_mem(cx, to_read))?;
157 let num = buf.as_ref().len() as u64;
158 if num > *remaining {
159 *remaining = 0;
160 } else if num == 0 {
161 return Poll::Ready(Err(io::Error::new(
162 io::ErrorKind::UnexpectedEof,
163 IncompleteBody,
164 )));
165 } else {
166 *remaining -= num;
167 }
168 Poll::Ready(Ok(Frame::data(buf)))
169 }
170 }
171 Chunked {
172 ref mut state,
173 ref mut chunk_len,
174 ref mut extensions_cnt,
175 ref mut trailers_buf,
176 ref mut trailers_cnt,
177 ref h1_max_headers,
178 ref h1_max_header_size,
179 } => {
180 let h1_max_headers = h1_max_headers.unwrap_or(DEFAULT_MAX_HEADERS);
181 let h1_max_header_size = h1_max_header_size.unwrap_or(TRAILER_LIMIT);
182 loop {
183 let mut buf = None;
184 *state = ready!(state.step(
186 cx,
187 body,
188 StepArgs {
189 chunk_size: chunk_len,
190 extensions_cnt,
191 chunk_buf: &mut buf,
192 trailers_buf,
193 trailers_cnt,
194 max_headers_cnt: h1_max_headers,
195 max_headers_bytes: h1_max_header_size,
196 }
197 ))?;
198 if *state == ChunkedState::End {
199 trace!("end of chunked");
200
201 if trailers_buf.is_some() {
202 trace!("found possible trailers");
203
204 match decode_trailers(
205 &mut trailers_buf.take().expect("Trailer is None"),
206 *trailers_cnt,
207 ) {
208 Ok(headers) => {
209 return Poll::Ready(Ok(Frame::trailers(headers)));
210 }
211 Err(e) => {
212 return Poll::Ready(Err(e));
213 }
214 }
215 }
216
217 return Poll::Ready(Ok(Frame::data(Bytes::new())));
218 }
219 if let Some(buf) = buf {
220 return Poll::Ready(Ok(Frame::data(buf)));
221 }
222 }
223 }
224 Eof(ref mut is_eof) => {
225 if *is_eof {
226 Poll::Ready(Ok(Frame::data(Bytes::new())))
227 } else {
228 body.read_mem(cx, 8192).map_ok(|slice| {
232 *is_eof = slice.is_empty();
233 Frame::data(slice)
234 })
235 }
236 }
237 }
238 }
239
240 #[cfg(test)]
241 async fn decode_fut<R: MemRead>(&mut self, body: &mut R) -> Result<Frame<Bytes>, io::Error> {
242 futures_util::future::poll_fn(move |cx| self.decode(cx, body)).await
243 }
244}
245
246impl fmt::Debug for Decoder {
247 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
248 fmt::Debug::fmt(&self.kind, f)
249 }
250}
251
252macro_rules! byte (
253 ($rdr:ident, $cx:expr) => ({
254 let buf = ready!($rdr.read_mem($cx, 1))?;
255 if !buf.is_empty() {
256 buf[0]
257 } else {
258 return Poll::Ready(Err(io::Error::new(io::ErrorKind::UnexpectedEof,
259 "unexpected EOF during chunk size line")));
260 }
261 })
262);
263
264macro_rules! or_overflow {
265 ($e:expr) => (
266 match $e {
267 Some(val) => val,
268 None => return Poll::Ready(Err(io::Error::new(
269 io::ErrorKind::InvalidData,
270 "invalid chunk size: overflow",
271 ))),
272 }
273 )
274}
275
276macro_rules! put_u8 {
277 ($trailers_buf:expr, $byte:expr, $limit:expr) => {
278 $trailers_buf.put_u8($byte);
279
280 if $trailers_buf.len() >= $limit {
281 return Poll::Ready(Err(io::Error::new(
282 io::ErrorKind::InvalidData,
283 "chunk trailers bytes over limit",
284 )));
285 }
286 };
287}
288
289struct StepArgs<'a> {
290 chunk_size: &'a mut u64,
291 chunk_buf: &'a mut Option<Bytes>,
292 extensions_cnt: &'a mut u64,
293 trailers_buf: &'a mut Option<BytesMut>,
294 trailers_cnt: &'a mut usize,
295 max_headers_cnt: usize,
296 max_headers_bytes: usize,
297}
298
299impl ChunkedState {
300 fn new() -> ChunkedState {
301 ChunkedState::Start
302 }
303 fn step<R: MemRead>(
304 &self,
305 cx: &mut Context<'_>,
306 body: &mut R,
307 StepArgs {
308 chunk_size,
309 chunk_buf,
310 extensions_cnt,
311 trailers_buf,
312 trailers_cnt,
313 max_headers_cnt,
314 max_headers_bytes,
315 }: StepArgs<'_>,
316 ) -> Poll<Result<ChunkedState, io::Error>> {
317 use self::ChunkedState::*;
318 match *self {
319 Start => ChunkedState::read_start(cx, body, chunk_size),
320 Size => ChunkedState::read_size(cx, body, chunk_size),
321 SizeLws => ChunkedState::read_size_lws(cx, body),
322 Extension => ChunkedState::read_extension(cx, body, extensions_cnt),
323 SizeLf => ChunkedState::read_size_lf(cx, body, *chunk_size),
324 Body => ChunkedState::read_body(cx, body, chunk_size, chunk_buf),
325 BodyCr => ChunkedState::read_body_cr(cx, body),
326 BodyLf => ChunkedState::read_body_lf(cx, body),
327 Trailer => ChunkedState::read_trailer(cx, body, trailers_buf, max_headers_bytes),
328 TrailerLf => ChunkedState::read_trailer_lf(
329 cx,
330 body,
331 trailers_buf,
332 trailers_cnt,
333 max_headers_cnt,
334 max_headers_bytes,
335 ),
336 EndCr => ChunkedState::read_end_cr(cx, body, trailers_buf, max_headers_bytes),
337 EndLf => ChunkedState::read_end_lf(cx, body, trailers_buf, max_headers_bytes),
338 End => Poll::Ready(Ok(ChunkedState::End)),
339 }
340 }
341
342 fn read_start<R: MemRead>(
343 cx: &mut Context<'_>,
344 rdr: &mut R,
345 size: &mut u64,
346 ) -> Poll<Result<ChunkedState, io::Error>> {
347 trace!("Read chunk start");
348
349 let radix = 16;
350 match byte!(rdr, cx) {
351 b @ b'0'..=b'9' => {
352 *size = or_overflow!(size.checked_mul(radix));
353 *size = or_overflow!(size.checked_add(u64::from(b - b'0')));
354 }
355 b @ b'a'..=b'f' => {
356 *size = or_overflow!(size.checked_mul(radix));
357 *size = or_overflow!(size.checked_add(u64::from(b + 10 - b'a')));
358 }
359 b @ b'A'..=b'F' => {
360 *size = or_overflow!(size.checked_mul(radix));
361 *size = or_overflow!(size.checked_add(u64::from(b + 10 - b'A')));
362 }
363 _ => {
364 return Poll::Ready(Err(io::Error::new(
365 io::ErrorKind::InvalidInput,
366 "Invalid chunk size line: missing size digit",
367 )));
368 }
369 }
370
371 Poll::Ready(Ok(ChunkedState::Size))
372 }
373
374 fn read_size<R: MemRead>(
375 cx: &mut Context<'_>,
376 rdr: &mut R,
377 size: &mut u64,
378 ) -> Poll<Result<ChunkedState, io::Error>> {
379 trace!("Read chunk hex size");
380
381 let radix = 16;
382 match byte!(rdr, cx) {
383 b @ b'0'..=b'9' => {
384 *size = or_overflow!(size.checked_mul(radix));
385 *size = or_overflow!(size.checked_add(u64::from(b - b'0')));
386 }
387 b @ b'a'..=b'f' => {
388 *size = or_overflow!(size.checked_mul(radix));
389 *size = or_overflow!(size.checked_add(u64::from(b + 10 - b'a')));
390 }
391 b @ b'A'..=b'F' => {
392 *size = or_overflow!(size.checked_mul(radix));
393 *size = or_overflow!(size.checked_add(u64::from(b + 10 - b'A')));
394 }
395 b'\t' | b' ' => return Poll::Ready(Ok(ChunkedState::SizeLws)),
396 b';' => return Poll::Ready(Ok(ChunkedState::Extension)),
397 b'\r' => return Poll::Ready(Ok(ChunkedState::SizeLf)),
398 _ => {
399 return Poll::Ready(Err(io::Error::new(
400 io::ErrorKind::InvalidInput,
401 "Invalid chunk size line: Invalid Size",
402 )));
403 }
404 }
405 Poll::Ready(Ok(ChunkedState::Size))
406 }
407 fn read_size_lws<R: MemRead>(
408 cx: &mut Context<'_>,
409 rdr: &mut R,
410 ) -> Poll<Result<ChunkedState, io::Error>> {
411 trace!("read_size_lws");
412 match byte!(rdr, cx) {
413 b'\t' | b' ' => Poll::Ready(Ok(ChunkedState::SizeLws)),
415 b';' => Poll::Ready(Ok(ChunkedState::Extension)),
416 b'\r' => Poll::Ready(Ok(ChunkedState::SizeLf)),
417 _ => Poll::Ready(Err(io::Error::new(
418 io::ErrorKind::InvalidInput,
419 "Invalid chunk size linear white space",
420 ))),
421 }
422 }
423 fn read_extension<R: MemRead>(
424 cx: &mut Context<'_>,
425 rdr: &mut R,
426 extensions_cnt: &mut u64,
427 ) -> Poll<Result<ChunkedState, io::Error>> {
428 trace!("read_extension");
429 match byte!(rdr, cx) {
436 b'\r' => Poll::Ready(Ok(ChunkedState::SizeLf)),
437 b'\n' => Poll::Ready(Err(io::Error::new(
438 io::ErrorKind::InvalidData,
439 "invalid chunk extension contains newline",
440 ))),
441 _ => {
442 *extensions_cnt += 1;
443 if *extensions_cnt >= CHUNKED_EXTENSIONS_LIMIT {
444 Poll::Ready(Err(io::Error::new(
445 io::ErrorKind::InvalidData,
446 "chunk extensions over limit",
447 )))
448 } else {
449 Poll::Ready(Ok(ChunkedState::Extension))
450 }
451 } }
453 }
454 fn read_size_lf<R: MemRead>(
455 cx: &mut Context<'_>,
456 rdr: &mut R,
457 size: u64,
458 ) -> Poll<Result<ChunkedState, io::Error>> {
459 trace!("Chunk size is {:?}", size);
460 match byte!(rdr, cx) {
461 b'\n' => {
462 if size == 0 {
463 Poll::Ready(Ok(ChunkedState::EndCr))
464 } else {
465 debug!("incoming chunked header: {0:#X} ({0} bytes)", size);
466 Poll::Ready(Ok(ChunkedState::Body))
467 }
468 }
469 _ => Poll::Ready(Err(io::Error::new(
470 io::ErrorKind::InvalidInput,
471 "Invalid chunk size LF",
472 ))),
473 }
474 }
475
476 fn read_body<R: MemRead>(
477 cx: &mut Context<'_>,
478 rdr: &mut R,
479 rem: &mut u64,
480 buf: &mut Option<Bytes>,
481 ) -> Poll<Result<ChunkedState, io::Error>> {
482 trace!("Chunked read, remaining={:?}", rem);
483
484 let to_read = usize::try_from(*rem).unwrap_or(usize::MAX);
486 let slice = ready!(rdr.read_mem(cx, to_read))?;
487 let count = slice.len();
488
489 if count == 0 {
490 *rem = 0;
491 return Poll::Ready(Err(io::Error::new(
492 io::ErrorKind::UnexpectedEof,
493 IncompleteBody,
494 )));
495 }
496 *buf = Some(slice);
497 *rem -= count as u64;
498
499 if *rem > 0 {
500 Poll::Ready(Ok(ChunkedState::Body))
501 } else {
502 Poll::Ready(Ok(ChunkedState::BodyCr))
503 }
504 }
505 fn read_body_cr<R: MemRead>(
506 cx: &mut Context<'_>,
507 rdr: &mut R,
508 ) -> Poll<Result<ChunkedState, io::Error>> {
509 match byte!(rdr, cx) {
510 b'\r' => Poll::Ready(Ok(ChunkedState::BodyLf)),
511 _ => Poll::Ready(Err(io::Error::new(
512 io::ErrorKind::InvalidInput,
513 "Invalid chunk body CR",
514 ))),
515 }
516 }
517 fn read_body_lf<R: MemRead>(
518 cx: &mut Context<'_>,
519 rdr: &mut R,
520 ) -> Poll<Result<ChunkedState, io::Error>> {
521 match byte!(rdr, cx) {
522 b'\n' => Poll::Ready(Ok(ChunkedState::Start)),
523 _ => Poll::Ready(Err(io::Error::new(
524 io::ErrorKind::InvalidInput,
525 "Invalid chunk body LF",
526 ))),
527 }
528 }
529
530 fn read_trailer<R: MemRead>(
531 cx: &mut Context<'_>,
532 rdr: &mut R,
533 trailers_buf: &mut Option<BytesMut>,
534 h1_max_header_size: usize,
535 ) -> Poll<Result<ChunkedState, io::Error>> {
536 trace!("read_trailer");
537 let byte = byte!(rdr, cx);
538
539 put_u8!(
540 trailers_buf.as_mut().expect("trailers_buf is None"),
541 byte,
542 h1_max_header_size
543 );
544
545 match byte {
546 b'\r' => Poll::Ready(Ok(ChunkedState::TrailerLf)),
547 _ => Poll::Ready(Ok(ChunkedState::Trailer)),
548 }
549 }
550
551 fn read_trailer_lf<R: MemRead>(
552 cx: &mut Context<'_>,
553 rdr: &mut R,
554 trailers_buf: &mut Option<BytesMut>,
555 trailers_cnt: &mut usize,
556 h1_max_headers: usize,
557 h1_max_header_size: usize,
558 ) -> Poll<Result<ChunkedState, io::Error>> {
559 let byte = byte!(rdr, cx);
560 match byte {
561 b'\n' => {
562 if *trailers_cnt >= h1_max_headers {
563 return Poll::Ready(Err(io::Error::new(
564 io::ErrorKind::InvalidData,
565 "chunk trailers count overflow",
566 )));
567 }
568 *trailers_cnt += 1;
569
570 put_u8!(
571 trailers_buf.as_mut().expect("trailers_buf is None"),
572 byte,
573 h1_max_header_size
574 );
575
576 Poll::Ready(Ok(ChunkedState::EndCr))
577 }
578 _ => Poll::Ready(Err(io::Error::new(
579 io::ErrorKind::InvalidInput,
580 "Invalid trailer end LF",
581 ))),
582 }
583 }
584
585 fn read_end_cr<R: MemRead>(
586 cx: &mut Context<'_>,
587 rdr: &mut R,
588 trailers_buf: &mut Option<BytesMut>,
589 h1_max_header_size: usize,
590 ) -> Poll<Result<ChunkedState, io::Error>> {
591 let byte = byte!(rdr, cx);
592 match byte {
593 b'\r' => {
594 if let Some(trailers_buf) = trailers_buf {
595 put_u8!(trailers_buf, byte, h1_max_header_size);
596 }
597 Poll::Ready(Ok(ChunkedState::EndLf))
598 }
599 byte => {
600 match trailers_buf {
601 None => {
602 let mut buf = BytesMut::with_capacity(64);
604 buf.put_u8(byte);
605 *trailers_buf = Some(buf);
606 }
607 Some(ref mut trailers_buf) => {
608 put_u8!(trailers_buf, byte, h1_max_header_size);
609 }
610 }
611
612 Poll::Ready(Ok(ChunkedState::Trailer))
613 }
614 }
615 }
616 fn read_end_lf<R: MemRead>(
617 cx: &mut Context<'_>,
618 rdr: &mut R,
619 trailers_buf: &mut Option<BytesMut>,
620 h1_max_header_size: usize,
621 ) -> Poll<Result<ChunkedState, io::Error>> {
622 let byte = byte!(rdr, cx);
623 match byte {
624 b'\n' => {
625 if let Some(trailers_buf) = trailers_buf {
626 put_u8!(trailers_buf, byte, h1_max_header_size);
627 }
628 Poll::Ready(Ok(ChunkedState::End))
629 }
630 _ => Poll::Ready(Err(io::Error::new(
631 io::ErrorKind::InvalidInput,
632 "Invalid chunk end LF",
633 ))),
634 }
635 }
636}
637
638fn decode_trailers(buf: &mut BytesMut, count: usize) -> Result<HeaderMap, io::Error> {
640 let mut trailers = HeaderMap::new();
641 let mut headers = vec![httparse::EMPTY_HEADER; count];
642 let res = httparse::parse_headers(buf, &mut headers);
643 match res {
644 Ok(httparse::Status::Complete((_, headers))) => {
645 for header in headers {
646 use std::convert::TryFrom;
647 let name = match HeaderName::try_from(header.name) {
648 Ok(name) => name,
649 Err(_) => {
650 return Err(io::Error::new(
651 io::ErrorKind::InvalidInput,
652 format!("Invalid header name: {:?}", &header),
653 ));
654 }
655 };
656
657 let value = match HeaderValue::from_bytes(header.value) {
658 Ok(value) => value,
659 Err(_) => {
660 return Err(io::Error::new(
661 io::ErrorKind::InvalidInput,
662 format!("Invalid header value: {:?}", &header),
663 ));
664 }
665 };
666
667 trailers.append(name, value);
668 }
669
670 Ok(trailers)
671 }
672 Ok(httparse::Status::Partial) => Err(io::Error::new(
673 io::ErrorKind::InvalidInput,
674 "Partial header",
675 )),
676 Err(e) => Err(io::Error::new(io::ErrorKind::InvalidInput, e)),
677 }
678}
679
680#[derive(Debug)]
681struct IncompleteBody;
682
683impl fmt::Display for IncompleteBody {
684 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
685 write!(f, "end of file before message length reached")
686 }
687}
688
689impl StdError for IncompleteBody {}
690
691#[cfg(test)]
692mod tests {
693 use super::*;
694 use crate::rt::{Read, ReadBuf};
695 use std::pin::Pin;
696 use std::time::Duration;
697
698 impl MemRead for &[u8] {
699 fn read_mem(&mut self, _: &mut Context<'_>, len: usize) -> Poll<io::Result<Bytes>> {
700 let n = std::cmp::min(len, self.len());
701 if n > 0 {
702 let (a, b) = self.split_at(n);
703 let buf = Bytes::copy_from_slice(a);
704 *self = b;
705 Poll::Ready(Ok(buf))
706 } else {
707 Poll::Ready(Ok(Bytes::new()))
708 }
709 }
710 }
711
712 impl MemRead for &mut (dyn Read + Unpin) {
713 fn read_mem(&mut self, cx: &mut Context<'_>, len: usize) -> Poll<io::Result<Bytes>> {
714 let mut v = vec![0; len];
715 let mut buf = ReadBuf::new(&mut v);
716 ready!(Pin::new(self).poll_read(cx, buf.unfilled())?);
717 Poll::Ready(Ok(Bytes::copy_from_slice(buf.filled())))
718 }
719 }
720
721 impl MemRead for Bytes {
722 fn read_mem(&mut self, _: &mut Context<'_>, len: usize) -> Poll<io::Result<Bytes>> {
723 let n = std::cmp::min(len, self.len());
724 let ret = self.split_to(n);
725 Poll::Ready(Ok(ret))
726 }
727 }
728
729 #[cfg(not(miri))]
740 #[tokio::test]
741 async fn test_read_chunk_size() {
742 use std::io::ErrorKind::{InvalidData, InvalidInput, UnexpectedEof};
743
744 async fn read(s: &str) -> u64 {
745 let mut state = ChunkedState::new();
746 let rdr = &mut s.as_bytes();
747 let mut size = 0;
748 let mut ext_cnt = 0;
749 let mut trailers_cnt = 0;
750 loop {
751 let result = futures_util::future::poll_fn(|cx| {
752 state.step(
753 cx,
754 rdr,
755 StepArgs {
756 chunk_size: &mut size,
757 extensions_cnt: &mut ext_cnt,
758 chunk_buf: &mut None,
759 trailers_buf: &mut None,
760 trailers_cnt: &mut trailers_cnt,
761 max_headers_cnt: DEFAULT_MAX_HEADERS,
762 max_headers_bytes: TRAILER_LIMIT,
763 },
764 )
765 })
766 .await;
767 let desc = format!("read_size failed for {:?}", s);
768 state = result.expect(&desc);
769 if state == ChunkedState::Body || state == ChunkedState::EndCr {
770 break;
771 }
772 }
773 size
774 }
775
776 async fn read_err(s: &str, expected_err: io::ErrorKind) {
777 let mut state = ChunkedState::new();
778 let rdr = &mut s.as_bytes();
779 let mut size = 0;
780 let mut ext_cnt = 0;
781 let mut trailers_cnt = 0;
782 loop {
783 let result = futures_util::future::poll_fn(|cx| {
784 state.step(
785 cx,
786 rdr,
787 StepArgs {
788 chunk_size: &mut size,
789 extensions_cnt: &mut ext_cnt,
790 chunk_buf: &mut None,
791 trailers_buf: &mut None,
792 trailers_cnt: &mut trailers_cnt,
793 max_headers_cnt: DEFAULT_MAX_HEADERS,
794 max_headers_bytes: TRAILER_LIMIT,
795 },
796 )
797 })
798 .await;
799 state = match result {
800 Ok(s) => s,
801 Err(e) => {
802 assert!(
803 expected_err == e.kind(),
804 "Reading {:?}, expected {:?}, but got {:?}",
805 s,
806 expected_err,
807 e.kind()
808 );
809 return;
810 }
811 };
812 if state == ChunkedState::Body || state == ChunkedState::End {
813 panic!("Was Ok. Expected Err for {:?}", s);
814 }
815 }
816 }
817
818 assert_eq!(1, read("1\r\n").await);
819 assert_eq!(1, read("01\r\n").await);
820 assert_eq!(0, read("0\r\n").await);
821 assert_eq!(0, read("00\r\n").await);
822 assert_eq!(10, read("A\r\n").await);
823 assert_eq!(10, read("a\r\n").await);
824 assert_eq!(255, read("Ff\r\n").await);
825 assert_eq!(255, read("Ff \r\n").await);
826 read_err("F\rF", InvalidInput).await;
828 read_err("F", UnexpectedEof).await;
829 read_err("\r\n\r\n", InvalidInput).await;
831 read_err("\r\n", InvalidInput).await;
832 read_err("X\r\n", InvalidInput).await;
834 read_err("1X\r\n", InvalidInput).await;
835 read_err("-\r\n", InvalidInput).await;
836 read_err("-1\r\n", InvalidInput).await;
837 assert_eq!(1, read("1;extension\r\n").await);
839 assert_eq!(10, read("a;ext name=value\r\n").await);
840 assert_eq!(1, read("1;extension;extension2\r\n").await);
841 assert_eq!(1, read("1;;; ;\r\n").await);
842 assert_eq!(2, read("2; extension...\r\n").await);
843 assert_eq!(3, read("3 ; extension=123\r\n").await);
844 assert_eq!(3, read("3 ;\r\n").await);
845 assert_eq!(3, read("3 ; \r\n").await);
846 read_err("1 invalid extension\r\n", InvalidInput).await;
848 read_err("1 A\r\n", InvalidInput).await;
849 read_err("1;no CRLF", UnexpectedEof).await;
850 read_err("1;reject\nnewlines\r\n", InvalidData).await;
851 read_err("f0000000000000003\r\n", InvalidData).await;
853 }
854
855 #[cfg(not(miri))]
856 #[tokio::test]
857 async fn test_read_sized_early_eof() {
858 let mut bytes = &b"foo bar"[..];
859 let mut decoder = Decoder::length(10);
860 assert_eq!(
861 decoder
862 .decode_fut(&mut bytes)
863 .await
864 .unwrap()
865 .data_ref()
866 .unwrap()
867 .len(),
868 7
869 );
870 let e = decoder.decode_fut(&mut bytes).await.unwrap_err();
871 assert_eq!(e.kind(), io::ErrorKind::UnexpectedEof);
872 }
873
874 #[cfg(not(miri))]
875 #[tokio::test]
876 async fn test_read_chunked_early_eof() {
877 let mut bytes = &b"\
878 9\r\n\
879 foo bar\
880 "[..];
881 let mut decoder = Decoder::chunked(None, None);
882 assert_eq!(
883 decoder
884 .decode_fut(&mut bytes)
885 .await
886 .unwrap()
887 .data_ref()
888 .unwrap()
889 .len(),
890 7
891 );
892 let e = decoder.decode_fut(&mut bytes).await.unwrap_err();
893 assert_eq!(e.kind(), io::ErrorKind::UnexpectedEof);
894 }
895
896 #[cfg(not(miri))]
897 #[tokio::test]
898 async fn test_read_chunked_single_read() {
899 let mut mock_buf = &b"10\r\n1234567890abcdef\r\n0\r\n"[..];
900 let buf = Decoder::chunked(None, None)
901 .decode_fut(&mut mock_buf)
902 .await
903 .expect("decode")
904 .into_data()
905 .expect("unknown frame type");
906 assert_eq!(16, buf.len());
907 let result = String::from_utf8(buf.as_ref().to_vec()).expect("decode String");
908 assert_eq!("1234567890abcdef", &result);
909 }
910
911 #[tokio::test]
912 async fn test_read_chunked_with_missing_zero_digit() {
913 let mut mock_buf = &b"1\r\nZ\r\n\r\n\r\n"[..];
915 let mut decoder = Decoder::chunked(None, None);
916 let buf = decoder
917 .decode_fut(&mut mock_buf)
918 .await
919 .expect("decode")
920 .into_data()
921 .expect("unknown frame type");
922 assert_eq!("Z", buf);
923
924 let err = decoder
925 .decode_fut(&mut mock_buf)
926 .await
927 .expect_err("decode 2");
928 assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
929 }
930
931 #[tokio::test]
932 async fn test_read_chunked_extensions_over_limit() {
933 let per_chunk = super::CHUNKED_EXTENSIONS_LIMIT * 2 / 3;
936 let mut scratch = vec![];
937 for _ in 0..2 {
938 scratch.extend(b"1;");
939 scratch.extend(b"x".repeat(per_chunk as usize));
940 scratch.extend(b"\r\nA\r\n");
941 }
942 scratch.extend(b"0\r\n\r\n");
943 let mut mock_buf = Bytes::from(scratch);
944
945 let mut decoder = Decoder::chunked(None, None);
946 let buf1 = decoder
947 .decode_fut(&mut mock_buf)
948 .await
949 .expect("decode1")
950 .into_data()
951 .expect("unknown frame type");
952 assert_eq!(&buf1[..], b"A");
953
954 let err = decoder
955 .decode_fut(&mut mock_buf)
956 .await
957 .expect_err("decode2");
958 assert_eq!(err.kind(), io::ErrorKind::InvalidData);
959 assert_eq!(err.to_string(), "chunk extensions over limit");
960 }
961
962 #[cfg(not(miri))]
963 #[tokio::test]
964 async fn test_read_chunked_trailer_with_missing_lf() {
965 let mut mock_buf = &b"10\r\n1234567890abcdef\r\n0\r\nbad\r\r\n"[..];
966 let mut decoder = Decoder::chunked(None, None);
967 decoder.decode_fut(&mut mock_buf).await.expect("decode");
968 let e = decoder.decode_fut(&mut mock_buf).await.unwrap_err();
969 assert_eq!(e.kind(), io::ErrorKind::InvalidInput);
970 }
971
972 #[cfg(not(miri))]
973 #[tokio::test]
974 async fn test_read_chunked_after_eof() {
975 let mut mock_buf = &b"10\r\n1234567890abcdef\r\n0\r\n\r\n"[..];
976 let mut decoder = Decoder::chunked(None, None);
977
978 let buf = decoder
980 .decode_fut(&mut mock_buf)
981 .await
982 .unwrap()
983 .into_data()
984 .expect("unknown frame type");
985 assert_eq!(16, buf.len());
986 let result = String::from_utf8(buf.as_ref().to_vec()).expect("decode String");
987 assert_eq!("1234567890abcdef", &result);
988
989 let buf = decoder
991 .decode_fut(&mut mock_buf)
992 .await
993 .expect("decode")
994 .into_data()
995 .expect("unknown frame type");
996 assert_eq!(0, buf.len());
997
998 let buf = decoder
1000 .decode_fut(&mut mock_buf)
1001 .await
1002 .expect("decode")
1003 .into_data()
1004 .expect("unknown frame type");
1005 assert_eq!(0, buf.len());
1006 }
1007
1008 async fn read_async(mut decoder: Decoder, content: &[u8], block_at: usize) -> String {
1011 let mut outs = Vec::new();
1012
1013 let mut ins = crate::common::io::Compat::new(if block_at == 0 {
1014 tokio_test::io::Builder::new()
1015 .wait(Duration::from_millis(10))
1016 .read(content)
1017 .build()
1018 } else {
1019 tokio_test::io::Builder::new()
1020 .read(&content[..block_at])
1021 .wait(Duration::from_millis(10))
1022 .read(&content[block_at..])
1023 .build()
1024 });
1025
1026 let mut ins = &mut ins as &mut (dyn Read + Unpin);
1027
1028 loop {
1029 let buf = decoder
1030 .decode_fut(&mut ins)
1031 .await
1032 .expect("unexpected decode error")
1033 .into_data()
1034 .expect("unexpected frame type");
1035 if buf.is_empty() {
1036 break; }
1038 outs.extend(buf.as_ref());
1039 }
1040
1041 String::from_utf8(outs).expect("decode String")
1042 }
1043
1044 async fn all_async_cases(content: &str, expected: &str, decoder: Decoder) {
1047 let content_len = content.len();
1048 for block_at in 0..content_len {
1049 let actual = read_async(decoder.clone(), content.as_bytes(), block_at).await;
1050 assert_eq!(expected, &actual) }
1052 }
1053
1054 #[cfg(not(miri))]
1055 #[tokio::test]
1056 async fn test_read_length_async() {
1057 let content = "foobar";
1058 all_async_cases(content, content, Decoder::length(content.len() as u64)).await;
1059 }
1060
1061 #[cfg(not(miri))]
1062 #[tokio::test]
1063 async fn test_read_chunked_async() {
1064 let content = "3\r\nfoo\r\n3\r\nbar\r\n0\r\n\r\n";
1065 let expected = "foobar";
1066 all_async_cases(content, expected, Decoder::chunked(None, None)).await;
1067 }
1068
1069 #[cfg(not(miri))]
1070 #[tokio::test]
1071 async fn test_read_eof_async() {
1072 let content = "foobar";
1073 all_async_cases(content, content, Decoder::eof()).await;
1074 }
1075
1076 #[cfg(all(feature = "nightly", not(miri)))]
1077 #[bench]
1078 fn bench_decode_chunked_1kb(b: &mut test::Bencher) {
1079 let rt = new_runtime();
1080
1081 const LEN: usize = 1024;
1082 let mut vec = Vec::new();
1083 vec.extend(format!("{:x}\r\n", LEN).as_bytes());
1084 vec.extend(&[0; LEN][..]);
1085 vec.extend(b"\r\n");
1086 let content = Bytes::from(vec);
1087
1088 b.bytes = LEN as u64;
1089
1090 b.iter(|| {
1091 let mut decoder = Decoder::chunked(None, None);
1092 rt.block_on(async {
1093 let mut raw = content.clone();
1094 let chunk = decoder
1095 .decode_fut(&mut raw)
1096 .await
1097 .unwrap()
1098 .into_data()
1099 .unwrap();
1100 assert_eq!(chunk.len(), LEN);
1101 });
1102 });
1103 }
1104
1105 #[cfg(all(feature = "nightly", not(miri)))]
1106 #[bench]
1107 fn bench_decode_length_1kb(b: &mut test::Bencher) {
1108 let rt = new_runtime();
1109
1110 const LEN: usize = 1024;
1111 let content = Bytes::from(&[0; LEN][..]);
1112 b.bytes = LEN as u64;
1113
1114 b.iter(|| {
1115 let mut decoder = Decoder::length(LEN as u64);
1116 rt.block_on(async {
1117 let mut raw = content.clone();
1118 let chunk = decoder
1119 .decode_fut(&mut raw)
1120 .await
1121 .unwrap()
1122 .into_data()
1123 .unwrap();
1124 assert_eq!(chunk.len(), LEN);
1125 });
1126 });
1127 }
1128
1129 #[cfg(feature = "nightly")]
1130 fn new_runtime() -> tokio::runtime::Runtime {
1131 tokio::runtime::Builder::new_current_thread()
1132 .enable_all()
1133 .build()
1134 .expect("rt build")
1135 }
1136
1137 #[test]
1138 fn test_decode_trailers() {
1139 let mut buf = BytesMut::new();
1140 buf.extend_from_slice(
1141 b"Expires: Wed, 21 Oct 2015 07:28:00 GMT\r\nX-Stream-Error: failed to decode\r\n\r\n",
1142 );
1143 let headers = decode_trailers(&mut buf, 2).expect("decode_trailers");
1144 assert_eq!(headers.len(), 2);
1145 assert_eq!(
1146 headers.get("Expires").unwrap(),
1147 "Wed, 21 Oct 2015 07:28:00 GMT"
1148 );
1149 assert_eq!(headers.get("X-Stream-Error").unwrap(), "failed to decode");
1150 }
1151
1152 #[test]
1153 fn test_decode_trailers_preserves_duplicate_values() {
1154 let mut buf = BytesMut::new();
1155 buf.extend_from_slice(b"X-Trace: first\r\nX-Trace: second\r\n\r\n");
1156
1157 let headers = decode_trailers(&mut buf, 2).expect("decode_trailers");
1158 let values = headers
1159 .get_all("X-Trace")
1160 .iter()
1161 .map(|value| value.to_str().unwrap())
1162 .collect::<Vec<_>>();
1163
1164 assert_eq!(values, ["first", "second"]);
1165 }
1166
1167 #[tokio::test]
1168 async fn test_trailer_max_headers_enforced() {
1169 let h1_max_headers = 10;
1170 let mut scratch = vec![];
1171 scratch.extend(b"10\r\n1234567890abcdef\r\n0\r\n");
1172 for i in 0..=h1_max_headers {
1173 scratch.extend(format!("trailer{}: {}\r\n", i, i).as_bytes());
1174 }
1175 scratch.extend(b"\r\n");
1176 let mut mock_buf = Bytes::from(scratch);
1177
1178 let mut decoder = Decoder::chunked(Some(h1_max_headers), None);
1179
1180 let buf = decoder
1182 .decode_fut(&mut mock_buf)
1183 .await
1184 .unwrap()
1185 .into_data()
1186 .expect("unknown frame type");
1187 assert_eq!(16, buf.len());
1188
1189 let err = decoder
1191 .decode_fut(&mut mock_buf)
1192 .await
1193 .expect_err("trailer fields over limit");
1194 assert_eq!(err.kind(), io::ErrorKind::InvalidData);
1195 }
1196
1197 #[tokio::test]
1198 async fn test_trailer_max_headers_allows_exact_limit() {
1199 let h1_max_headers = 10;
1200 let mut scratch = vec![];
1201 scratch.extend(b"10\r\n1234567890abcdef\r\n0\r\n");
1202 for i in 0..h1_max_headers {
1203 scratch.extend(format!("trailer{}: {}\r\n", i, i).as_bytes());
1204 }
1205 scratch.extend(b"\r\n");
1206 let mut mock_buf = Bytes::from(scratch);
1207
1208 let mut decoder = Decoder::chunked(Some(h1_max_headers), None);
1209
1210 let buf = decoder
1211 .decode_fut(&mut mock_buf)
1212 .await
1213 .unwrap()
1214 .into_data()
1215 .expect("unknown frame type");
1216 assert_eq!(16, buf.len());
1217
1218 let trailers = decoder
1219 .decode_fut(&mut mock_buf)
1220 .await
1221 .expect("trailers at limit")
1222 .into_trailers()
1223 .expect("unknown frame type");
1224 assert_eq!(trailers.len(), h1_max_headers);
1225 }
1226
1227 #[tokio::test]
1228 async fn test_trailer_max_header_size_huge_trailer() {
1229 let max_header_size = 1024;
1230 let mut scratch = vec![];
1231 scratch.extend(b"10\r\n1234567890abcdef\r\n0\r\n");
1232 scratch.extend(format!("huge_trailer: {}\r\n", "x".repeat(max_header_size)).as_bytes());
1233 scratch.extend(b"\r\n");
1234 let mut mock_buf = Bytes::from(scratch);
1235
1236 let mut decoder = Decoder::chunked(None, Some(max_header_size));
1237
1238 let buf = decoder
1240 .decode_fut(&mut mock_buf)
1241 .await
1242 .unwrap()
1243 .into_data()
1244 .expect("unknown frame type");
1245 assert_eq!(16, buf.len());
1246
1247 let err = decoder
1249 .decode_fut(&mut mock_buf)
1250 .await
1251 .expect_err("trailers over limit");
1252 assert_eq!(err.kind(), io::ErrorKind::InvalidData);
1253 }
1254
1255 #[tokio::test]
1256 async fn test_trailer_max_header_size_many_small_trailers() {
1257 let max_headers = 10;
1258 let header_size = 64;
1259 let mut scratch = vec![];
1260 scratch.extend(b"10\r\n1234567890abcdef\r\n0\r\n");
1261
1262 for i in 0..max_headers {
1263 scratch.extend(format!("trailer{}: {}\r\n", i, "x".repeat(header_size)).as_bytes());
1264 }
1265
1266 scratch.extend(b"\r\n");
1267 let mut mock_buf = Bytes::from(scratch);
1268
1269 let mut decoder = Decoder::chunked(None, Some(max_headers * header_size));
1270
1271 let buf = decoder
1273 .decode_fut(&mut mock_buf)
1274 .await
1275 .unwrap()
1276 .into_data()
1277 .expect("unknown frame type");
1278 assert_eq!(16, buf.len());
1279
1280 let err = decoder
1282 .decode_fut(&mut mock_buf)
1283 .await
1284 .expect_err("trailers over limit");
1285 assert_eq!(err.kind(), io::ErrorKind::InvalidData);
1286 }
1287}