summaryrefslogtreecommitdiff
path: root/src/http_chunk.c
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2020-12-14 19:55:00 -0500
committerGlenn Strauss <gstrauss@gluelogic.com>2020-12-14 19:55:00 -0500
commit3230c6ef172b2aa2833632f86c1f97bb8ac59471 (patch)
treef8f71a26b699c10bf4879d88f56f84178265090b /src/http_chunk.c
parent163cb8be2852aa922276eeba5259bcf8cea566b3 (diff)
downloadlighttpd-git-3230c6ef172b2aa2833632f86c1f97bb8ac59471.tar.gz
[core] reject excess data after chunked encoding (#3046)
reject excess data after chunked encoding when parsing backend response x-ref: "Failure on second request in http proxy backend" https://redmine.lighttpd.net/issues/3046
Diffstat (limited to 'src/http_chunk.c')
-rw-r--r--src/http_chunk.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/src/http_chunk.c b/src/http_chunk.c
index 09f4d4a6..20d6429c 100644
--- a/src/http_chunk.c
+++ b/src/http_chunk.c
@@ -314,8 +314,7 @@ void http_chunk_close(request_st * const r) {
static int
http_chunk_decode_append_data (request_st * const r, const char *mem, off_t len)
{
- /*(silently discard data, if any, after final \r\n)*/
- if (r->gw_dechunk->done) return 0;
+ if (r->gw_dechunk->done) return -1; /*(excess data)*/
buffer * const h = &r->gw_dechunk->b;
off_t te_chunked = r->gw_dechunk->gw_chunked;
@@ -372,7 +371,6 @@ http_chunk_decode_append_data (request_st * const r, const char *mem, off_t len)
* request-ending blank line "\r\n" */
if (len - hsz == 2 && p[0] == '\r' && p[1] == '\n') {
/* common case with no trailers; final \r\n received */
- /*(silently discard data, if any, after final \r\n)*/
#if 0 /*(avoid allocation for common case; users must check)*/
if (buffer_is_empty(h))
buffer_copy_string_len(h, CONST_STR_LEN("0\r\n\r\n"));
@@ -404,14 +402,28 @@ http_chunk_decode_append_data (request_st * const r, const char *mem, off_t len)
}
buffer_append_string_len(h, mem, hsz);
hlen += (uint32_t)hsz; /* uint32_t fits in (buffer *) */
+ if (hlen < 2) break;
+ p = h->ptr;
+ if (p[0] == '\r' && p[1] == '\n') {
+ if (hlen > 2) return -1; /*(excess data)*/
+ /* common case with no trailers; final \r\n received */
+ #if 0 /*(avoid allocation for common case; users must check)*/
+ if (buffer_is_empty(h))
+ buffer_copy_string_len(h, CONST_STR_LEN("0\r\n\r\n"));
+ #else
+ buffer_clear(h);
+ #endif
+ r->gw_dechunk->done = r->http_status;
+ break;
+ }
if (hlen < 4) break;
- p = h->ptr + hlen - 4;
+ p += hlen - 4;
if (p[0]=='\r'&&p[1]=='\n'&&p[2]=='\r'&&p[3]=='\n')
r->gw_dechunk->done = r->http_status;
else if ((p = strstr(h->ptr, "\r\n\r\n"))) {
r->gw_dechunk->done = r->http_status;
- /*(silently discard data, if any, after final \r\n)*/
buffer_string_set_length(h, (uint32_t)(p+4-h->ptr));
+ if (p+4 != h->ptr+hlen) return -1; /*(excess data)*/
}
break;
}