Skip to content

Commit

Permalink
http: reject content-length duplicates with different values
Browse files Browse the repository at this point in the history
  • Loading branch information
michaldziuba03 committed Jul 22, 2024
1 parent 9075c11 commit ba80330
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 3 deletions.
2 changes: 0 additions & 2 deletions src/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ void lx_http_handle_data(lx_connection_t *conn) {
lx_close(conn);
return;
}

log_info("Received: %d bytes, buffer size: %ld, nread size: %ld", bytes, conn->size, req->parser.nread);

lx_buf_t input = { .buf = conn->buf, .size = conn->size };
int parser_code = lx_http_parser_exec(&req->parser, &input);
Expand Down
16 changes: 16 additions & 0 deletions src/http_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ const char *lx_http_map_code(lx_parser_status_t code) {
return "Limit of max headers exceeded.";
case LX_INVALID_CONTENT_LENGTH:
return "Invalid content-length header value.";
case LX_CONTENT_LENGTH_DUPLICATE:
return "Received duplicated content-length header with different value.";
default:
return "Unknown HTTP parser code.";
}
Expand Down Expand Up @@ -111,6 +113,7 @@ void lx_http_parser_init(lx_http_parser_t *parser) {
parser->nread = 0;
parser->nheaders = 0;
parser->content_length = 0;
parser->content_length_received = 0;

parser->header_key.start = NULL;
parser->header_key.size = 0;
Expand All @@ -125,6 +128,13 @@ void lx_http_parser_init(lx_http_parser_t *parser) {
parser->method.size = 0;
}

enum lx_http_connection_header {
LX_KEEP_ALIVE,
LX_UPGRADE,
LX_CLOSE,
LX_INVALID
};

// TODO: it would be more performant to detect specific headers during processing
int lx_on_header_complete(lx_http_parser_t *parser) {
http_raw_header_t *header = parser->req->raw_headers + parser->nheaders;
Expand All @@ -139,7 +149,13 @@ int lx_on_header_complete(lx_http_parser_t *parser) {
if (result == -1) {
return LX_INVALID_CONTENT_LENGTH;
}

if (parser->content_length_received && parser->content_length != result) {
return LX_CONTENT_LENGTH_DUPLICATE;
}

parser->content_length = result;
parser->content_length_received = 1;
}
break;
default:
Expand Down
4 changes: 3 additions & 1 deletion src/http_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ typedef enum lx_parser_status {
LX_INVALID_HEADER_KEY_CHAR,
LX_INVALID_HEADER_VALUE_CHAR,
LX_TOO_MANY_HEADERS,
LX_INVALID_CONTENT_LENGTH
LX_INVALID_CONTENT_LENGTH,
LX_CONTENT_LENGTH_DUPLICATE
} lx_parser_status_t;

typedef struct lx_buf {
Expand Down Expand Up @@ -63,6 +64,7 @@ typedef struct lx_http_parser {
slice_t header_key;
slice_t header_value;
size_t content_length;
int content_length_received: 1;
unsigned nheaders;
} lx_http_parser_t;

Expand Down
2 changes: 2 additions & 0 deletions src/http_request.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ typedef struct http_raw_header {
struct http_request_s {
char *path;
http_method_t method;
int persistent: 1;
char *body;
size_t body_size;
lx_http_parser_t parser;
Expand All @@ -71,6 +72,7 @@ static http_request_t *http_request_alloc() {
req->connection = NULL;
lx_http_parser_init(&req->parser);
req->parser.req = req;
req->persistent = 1;

return req;
}
Expand Down

0 comments on commit ba80330

Please sign in to comment.