diff options
author | Glenn Strauss <gstrauss@gluelogic.com> | 2020-12-14 19:55:00 -0500 |
---|---|---|
committer | Glenn Strauss <gstrauss@gluelogic.com> | 2020-12-14 19:55:00 -0500 |
commit | 3230c6ef172b2aa2833632f86c1f97bb8ac59471 (patch) | |
tree | f8f71a26b699c10bf4879d88f56f84178265090b /src/http_chunk.c | |
parent | 163cb8be2852aa922276eeba5259bcf8cea566b3 (diff) | |
download | lighttpd-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.c | 22 |
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; } |