From c02b2427e8d266c51d246bcb5ed410f3f0ae338f Mon Sep 17 00:00:00 2001 From: Seven Du Date: Sat, 6 Sep 2014 19:35:05 +0800 Subject: [PATCH] refactor http parsing and prevent read body more than content-length --- src/include/switch_utils.h | 5 +++-- src/mod/endpoints/mod_verto/mod_verto.c | 27 +++++++++++++++++-------- src/switch_utils.c | 11 +++++----- 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h index 67fee60c3c..d7c07e7171 100644 --- a/src/include/switch_utils.h +++ b/src/include/switch_utils.h @@ -1116,13 +1116,14 @@ typedef struct switch_http_request_s { switch_bool_t keepalive; const char *content_type; switch_size_t content_length; + switch_size_t bytes_header; + switch_size_t bytes_read; + switch_size_t bytes_buffered; switch_event_t *headers; void *user_data; /* private user data */ /* private members used by the parser internally */ char *_buffer; - const char *_unparsed_data; - switch_size_t _unparsed_len; switch_bool_t _destroy_headers; } switch_http_request_t; diff --git a/src/mod/endpoints/mod_verto/mod_verto.c b/src/mod/endpoints/mod_verto/mod_verto.c index 1f3ff1bad3..2a08473f72 100644 --- a/src/mod/endpoints/mod_verto/mod_verto.c +++ b/src/mod/endpoints/mod_verto/mod_verto.c @@ -1287,17 +1287,29 @@ static uint8_t *http_stream_read(switch_stream_handle_t *handle, int *len) jsock_t *jsock = r->user_data; wsh_t *wsh = &jsock->ws; - *len = r->_unparsed_len; + *len = r->bytes_buffered - r->bytes_read; - if (*len) { // we already read part of the body - r->_unparsed_len = 0; // reset for the next read - return (uint8_t *)r->_unparsed_data; + if (*len > 0) { // we already read part of the body + uint8_t *data = (uint8_t *)wsh->buffer + r->bytes_read; + r->bytes_read = r->bytes_buffered; + return data; } - if ((*len = ws_raw_read(wsh, wsh->buffer, 4096, wsh->block)) < 0) { + if (r->content_length && (r->bytes_read - r->bytes_header) >= r->content_length) { + *len = 0; return NULL; } + *len = r->content_length - (r->bytes_read - r->bytes_header); + *len = *len > sizeof(wsh->buffer) ? sizeof(wsh->buffer) : *len; + + if ((*len = ws_raw_read(wsh, wsh->buffer, *len, wsh->block)) <= 0) { + *len = 0; + return NULL; + } + + r->bytes_read += *len; + return (uint8_t *)wsh->buffer; } @@ -1453,9 +1465,8 @@ static void http_run(jsock_t *jsock) goto request_err; } - if (request._unparsed_len) { - bytes += request._unparsed_len; - memcpy(buffer, request._unparsed_data, bytes); + if ((bytes = request.bytes_buffered - (request.bytes_read - request.bytes_header)) > 0) { + memcpy(buffer, jsock->ws.buffer + request.bytes_read, bytes); } while(bytes < request.content_length) { diff --git a/src/switch_utils.c b/src/switch_utils.c index c08b5ff27d..c3e044bbaf 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -3675,10 +3675,10 @@ SWITCH_DECLARE(switch_status_t) switch_http_parse_header(char *buffer, uint32_t request->_buffer = strdup(buffer); request->method = request->_buffer; - if (body && *body) { - request->_unparsed_data = body; - request->_unparsed_len = datalen - (body - buffer); - switch_assert(request->_unparsed_len > 0); + request->bytes_buffered = datalen; + if (body) { + request->bytes_header = body - buffer; + request->bytes_read = body - buffer; } p = strchr(request->method, ' '); @@ -3796,7 +3796,8 @@ SWITCH_DECLARE(void) switch_http_dump_request(switch_http_request_t *request) if (request->referer) printf("referer: %s\n", request->referer); if (request->user) printf("user: %s\n", request->user); if (request->keepalive) printf("uri: %d\n", request->keepalive); - if (request->_unparsed_data) printf("body: %p\n", request->_unparsed_data); + if (request->content_type) printf("uri: %s\n", request->content_type); + if (request->content_length) printf("uri: %" SWITCH_SIZE_T_FMT "\n", request->content_length); { switch_event_header_t *header = request->headers->headers;