Validate received content-length header (#43)

If a content-length header is provided, the value should match the sum
of all data frame lengths. If there is a mismatch, then the stream is
reset.
This commit is contained in:
Carl Lerche
2017-08-31 12:40:02 -04:00
committed by GitHub
parent 0b1fbc4b39
commit 6fd9674759
4 changed files with 134 additions and 6 deletions

View File

@@ -71,6 +71,18 @@ pub(super) struct Stream<B, P>
/// The stream's pending push promises
pub pending_push_promises: store::Queue<B, NextAccept, P>,
/// Validate content-length headers
pub content_length: ContentLength,
}
/// State related to validating a stream's content-length
#[derive(Debug)]
pub enum ContentLength {
Omitted,
Head,
Remaining(u64),
}
#[derive(Debug)]
@@ -130,6 +142,7 @@ impl<B, P> Stream<B, P>
pending_recv: buffer::Deque::new(),
recv_task: None,
pending_push_promises: store::Queue::new(),
content_length: ContentLength::Omitted,
}
}
@@ -144,6 +157,30 @@ impl<B, P> Stream<B, P>
}
}
/// Returns `Err` when the decrement cannot be completed due to overflow.
pub fn dec_content_length(&mut self, len: usize) -> Result<(), ()> {
match self.content_length {
ContentLength::Remaining(ref mut rem) => {
match rem.checked_sub(len as u64) {
Some(val) => *rem = val,
None => return Err(()),
}
}
ContentLength::Head => return Err(()),
_ => {}
}
Ok(())
}
pub fn ensure_content_length_zero(&self) -> Result<(), ()> {
match self.content_length {
ContentLength::Remaining(0) => Ok(()),
ContentLength::Remaining(_) => Err(()),
_ => Ok(()),
}
}
pub fn notify_send(&mut self) {
if let Some(task) = self.send_task.take() {
task.notify();
@@ -244,3 +281,14 @@ impl store::Next for NextWindowUpdate {
stream.is_pending_window_update = val;
}
}
// ===== impl ContentLength =====
impl ContentLength {
pub fn is_head(&self) -> bool {
match *self {
ContentLength::Head => true,
_ => false,
}
}
}