mirror of
https://github.com/libevent/libevent.git
synced 2025-01-31 09:12:55 +08:00
reject negative content-length headers
svn:r894
This commit is contained in:
parent
cb7c3bd671
commit
707f67849a
@ -113,6 +113,7 @@ Changes in current version:
|
||||
o Support 64-bit integers in RPC structs
|
||||
o Correct handling of trailing headers in chunked replies; from Scott Lamb.
|
||||
o Support multi-line HTTP headers; based on a patch from Moshe Litvin
|
||||
o Reject negative Content-Length headers; anonymous bug report
|
||||
|
||||
Changes in 1.4.0:
|
||||
o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr.
|
||||
|
19
http.c
19
http.c
@ -395,7 +395,7 @@ evhttp_make_header_request(struct evhttp_connection *evcon,
|
||||
evhttp_find_header(req->output_headers, "Content-Length") == NULL){
|
||||
char size[12];
|
||||
evutil_snprintf(size, sizeof(size), "%ld",
|
||||
(long)EVBUFFER_LENGTH(req->output_buffer));
|
||||
(long)EVBUFFER_LENGTH(req->output_buffer));
|
||||
evhttp_add_header(req->output_headers, "Content-Length", size);
|
||||
}
|
||||
}
|
||||
@ -726,6 +726,7 @@ evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf)
|
||||
while ((len = EVBUFFER_LENGTH(buf)) > 0) {
|
||||
if (req->ntoread < 0) {
|
||||
/* Read chunk size */
|
||||
ev_int64_t ntoread;
|
||||
char *p = evbuffer_readln(buf, NULL, EVBUFFER_EOL_CRLF);
|
||||
char *endp;
|
||||
int error;
|
||||
@ -736,13 +737,16 @@ evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf)
|
||||
mm_free(p);
|
||||
continue;
|
||||
}
|
||||
req->ntoread = evutil_strtoll(p, &endp, 16);
|
||||
error = *p == '\0' || (*endp != '\0' && *endp != ' ');
|
||||
ntoread = evutil_strtoll(p, &endp, 16);
|
||||
error = (*p == '\0' ||
|
||||
(*endp != '\0' && *endp != ' ') ||
|
||||
ntoread < 0);
|
||||
mm_free(p);
|
||||
if (error) {
|
||||
/* could not get chunk size */
|
||||
return (DATA_CORRUPTED);
|
||||
}
|
||||
req->ntoread = ntoread;
|
||||
if (req->ntoread == 0) {
|
||||
/* Last chunk */
|
||||
return (ALL_DATA_READ);
|
||||
@ -1503,12 +1507,13 @@ evhttp_get_body_length(struct evhttp_request *req)
|
||||
req->ntoread = -1;
|
||||
} else {
|
||||
char *endp;
|
||||
req->ntoread = evutil_strtoll(content_length, &endp, 10);
|
||||
if (*content_length == '\0' || *endp != '\0') {
|
||||
event_warnx("%s: illegal content length: %s",
|
||||
__func__, content_length);
|
||||
ev_int64_t ntoread = evutil_strtoll(content_length, &endp, 10);
|
||||
if (*content_length == '\0' || *endp != '\0' || ntoread < 0) {
|
||||
event_debug(("%s: illegal content length: %s",
|
||||
__func__, content_length));
|
||||
return (-1);
|
||||
}
|
||||
req->ntoread = ntoread;
|
||||
}
|
||||
|
||||
event_debug(("%s: bytes to read: %d (in buffer %ld)\n",
|
||||
|
@ -243,6 +243,12 @@ http_basic_cb(struct evhttp_request *req, void *arg)
|
||||
test_ok++;
|
||||
}
|
||||
}
|
||||
|
||||
/* injecting a bad content-length */
|
||||
if (evhttp_find_header(req->input_headers, "X-Negative"))
|
||||
evhttp_add_header(req->output_headers,
|
||||
"Content-Length", "-100");
|
||||
|
||||
/* allow sending of an empty reply */
|
||||
evhttp_send_reply(req, HTTP_OK, "Everything is fine",
|
||||
!empty ? evb : NULL);
|
||||
@ -2183,6 +2189,64 @@ http_multi_line_header_test(void)
|
||||
fprintf(stdout, "OK\n");
|
||||
}
|
||||
|
||||
static void
|
||||
http_request_bad(struct evhttp_request *req, void *arg)
|
||||
{
|
||||
if (req != NULL) {
|
||||
fprintf(stderr, "FAILED\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
test_ok = 1;
|
||||
event_loopexit(NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
http_negative_content_length_test(void)
|
||||
{
|
||||
short port = -1;
|
||||
struct evhttp_connection *evcon = NULL;
|
||||
struct evhttp_request *req = NULL;
|
||||
|
||||
test_ok = 0;
|
||||
fprintf(stdout, "Testing HTTP Negative Content Length: ");
|
||||
|
||||
http = http_setup(&port, NULL);
|
||||
|
||||
evcon = evhttp_connection_new("127.0.0.1", port);
|
||||
if (evcon == NULL) {
|
||||
fprintf(stdout, "FAILED\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point, we want to schedule a request to the HTTP
|
||||
* server using our make request method.
|
||||
*/
|
||||
|
||||
req = evhttp_request_new(http_request_bad, NULL);
|
||||
|
||||
/* Cause the response to have a negative content-length */
|
||||
evhttp_add_header(req->output_headers, "X-Negative", "makeitso");
|
||||
|
||||
/* We give ownership of the request to the connection */
|
||||
if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
|
||||
fprintf(stdout, "FAILED\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
event_dispatch();
|
||||
|
||||
evhttp_free(http);
|
||||
|
||||
if (test_ok != 1) {
|
||||
fprintf(stdout, "FAILED\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fprintf(stdout, "OK\n");
|
||||
}
|
||||
|
||||
void
|
||||
http_suite(void)
|
||||
{
|
||||
@ -2204,6 +2268,7 @@ http_suite(void)
|
||||
http_dispatcher_test();
|
||||
|
||||
http_multi_line_header_test();
|
||||
http_negative_content_length_test();
|
||||
|
||||
http_incomplete_test(0 /* use_timeout */);
|
||||
http_incomplete_test(1 /* use_timeout */);
|
||||
|
Loading…
x
Reference in New Issue
Block a user