micro-http: unsigned Content-Length...

...and a bunch of fixes for unchecked unsigned arithmetic
in connection.rs. Added more unit tests too that exercise
failure cases for over/underflows in mathematic operations.

Fixes #1977

Signed-off-by: Alexandra Iordache <aghecen@amazon.com>
Signed-off-by: YUAN LYU <lyuyuan92@gmail.com>
This commit is contained in:
Alexandra Iordache
2020-06-29 16:16:03 +03:00
committed by Adrian Catangiu
parent 48b8f179c8
commit 88de0ed16b
4 changed files with 358 additions and 43 deletions

View File

@@ -74,7 +74,7 @@ impl Header {
pub struct Headers {
/// The `Content-Length` header field tells us how many bytes we need to receive
/// from the source after the headers.
content_length: i32,
content_length: u32,
/// The `Expect` header field is set when the headers contain the entry "Expect: 100-continue".
/// This means that, per HTTP/1.1 specifications, we must send a response with the status code
/// 100 after we have received the headers in order to receive the body of the request. This
@@ -134,7 +134,7 @@ impl Headers {
}
if let Ok(head) = Header::try_from(entry[0].as_bytes()) {
match head {
Header::ContentLength => match entry[1].trim().parse::<i32>() {
Header::ContentLength => match entry[1].trim().parse::<u32>() {
Ok(content_length) => {
self.content_length = content_length;
Ok(())
@@ -180,7 +180,7 @@ impl Headers {
}
/// Returns the content length of the body.
pub fn content_length(&self) -> i32 {
pub fn content_length(&self) -> u32 {
self.content_length
}
@@ -318,7 +318,7 @@ mod tests {
use super::*;
impl Headers {
pub fn new(content_length: i32, expect: bool, chunked: bool) -> Self {
pub fn new(content_length: u32, expect: bool, chunked: bool) -> Self {
Self {
content_length,
expect,
@@ -480,6 +480,12 @@ mod tests {
assert!(header
.parse_header_line(b"Accept: application/json-patch")
.is_err());
// Invalid content length.
assert_eq!(
header.parse_header_line(b"Content-Length: -1"),
Err(RequestError::InvalidHeader)
);
}
#[test]

View File

@@ -16,6 +16,10 @@ pub mod ascii {
/// Errors associated with parsing the HTTP Request from a u8 slice.
#[derive(Debug, PartialEq)]
pub enum RequestError {
/// No request was pending while the request body was being parsed.
BodyWithoutPendingRequest,
/// No request was pending while the request headers were being parsed.
HeadersWithoutPendingRequest,
/// The HTTP Method is not supported or it is invalid.
InvalidHttpMethod(&'static str),
/// Request URI is invalid.
@@ -37,6 +41,14 @@ pub enum RequestError {
impl Display for RequestError {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
match self {
Self::BodyWithoutPendingRequest => write!(
f,
"No request was pending while the request body was being parsed."
),
Self::HeadersWithoutPendingRequest => write!(
f,
"No request was pending while the request headers were being parsed."
),
Self::InvalidHttpMethod(inner) => write!(f, "Invalid HTTP Method: {}", inner),
Self::InvalidUri(inner) => write!(f, "Invalid URI: {}", inner),
Self::InvalidHttpVersion(inner) => write!(f, "Invalid HTTP Version: {}", inner),
@@ -322,6 +334,14 @@ mod tests {
#[test]
fn test_display_request_error() {
assert_eq!(
format!("{}", RequestError::BodyWithoutPendingRequest),
"No request was pending while the request body was being parsed."
);
assert_eq!(
format!("{}", RequestError::HeadersWithoutPendingRequest),
"No request was pending while the request headers were being parsed."
);
assert_eq!(
format!("{}", RequestError::InvalidHeader),
"Invalid header."