[core] limit num ranges in Range requests
parse Range header prior to constructing ranged response
@@ -331,7 +331,7 @@ handler_t http_response_reqbody_read_error (request_st * const r, int http_statu
static int http_response_parse_range(request_st * const r, buffer * const path, stat_cache_entry * const sce, const char * const range) {
- int multipart = 0;
+ int n = 0;
int error;
off_t start, end;
const char *s, *minus;
@@ -339,6 +339,7 @@ static int http_response_parse_range(request_st * const r, buffer * const path,
const buffer *content_type =
http_header_response_get(r, HTTP_HEADER_CONTENT_TYPE,
CONST_STR_LEN("Content-Type"));
+ off_t ranges[16];
start = 0;
end = sce->st.st_size - 1;
@@ -383,7 +384,6 @@ static int http_response_parse_range(request_st * const r, buffer * const path,
end = sce->st.st_size - 1;
start = sce->st.st_size + le;
} else if (*err == ',') {
- multipart = 1;
s = err + 1;
end = sce->st.st_size - 1;
@@ -404,7 +404,6 @@ static int http_response_parse_range(request_st * const r, buffer * const path,
start = la;
} else if (*(err + 1) == ',') {
- multipart = 1;
s = err + 2;
end = sce->st.st_size - 1;
@@ -429,7 +428,6 @@ static int http_response_parse_range(request_st * const r, buffer * const path,
end = le;
start = la;
} else if (*err == ',') {
- multipart = 1;
s = err + 1;
end = le;
@@ -455,7 +453,25 @@ static int http_response_parse_range(request_st * const r, buffer * const path,
}
if (!error) {
- if (multipart) {
+ if (n < (int)(sizeof(ranges)/sizeof(*ranges))) {
+ ranges[n] = start;
+ ranges[n+1] = end;
+ n += 2;
+ }
+ else { /* excessive num ranges in request */
+ error = 1;
+ r->http_status = 416;
+ }
+ }
+ }
+
+ /* something went wrong */
+ if (error) return -1;
+
+ for (int i = 0; i < n; i += 2) {
+ start = ranges[i];
+ end = ranges[i+1];
+ if (n > 2) {
/* write boundary-header */
buffer *b = r->tmp_buf;
buffer_copy_string_len(b, CONST_STR_LEN("\r\n--"));
@@ -484,14 +500,10 @@ static int http_response_parse_range(request_st * const r, buffer * const path,
chunkqueue_append_file(&r->write_queue, path, start, end - start + 1);
r->content_length += end - start + 1;
}
- }
-
- /* something went wrong */
- if (error) return -1;
buffer * const tb = r->tmp_buf;
- if (multipart) {
+ if (n > 2) {
/* add boundary end */
buffer_copy_string_len(tb, "\r\n--", 4);
buffer_append_string_len(tb, boundary, sizeof(boundary)-1);
