summaryrefslogtreecommitdiff
path: root/src/http-header-glue.c
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2021-07-24 00:59:48 -0400
committerGlenn Strauss <gstrauss@gluelogic.com>2021-09-08 15:06:06 -0400
commit833d658729a65d577b2d92b298d61b5316232396 (patch)
tree9f470b67556ee95ccb546d652efffbf5eaeaa47d /src/http-header-glue.c
parent2ef31a1b3fa6b5392cbdcc7c3147432612003382 (diff)
downloadlighttpd-git-833d658729a65d577b2d92b298d61b5316232396.tar.gz
[core] http_response_append_{buffer,mem}()
manage r->resp_body_scratchpad in new funcs http_response_append_buffer() http_response_append_mem() rather than http_chunk_decode_append_buffer() http_chunk_decode_append_mem() which now only decode chunked encoding, more apropos for the func names
Diffstat (limited to 'src/http-header-glue.c')
-rw-r--r--src/http-header-glue.c61
1 files changed, 59 insertions, 2 deletions
diff --git a/src/http-header-glue.c b/src/http-header-glue.c
index 07845613..b5c102b9 100644
--- a/src/http-header-glue.c
+++ b/src/http-header-glue.c
@@ -702,6 +702,58 @@ void http_response_upgrade_read_body_unknown(request_st * const r) {
}
+static int http_response_append_buffer(request_st * const r, buffer * const mem) {
+ /* Note: this routine is separate from http_response_append_mem() to
+ * potentially avoid copying in http_chunk_append_buffer(). Otherwise this
+ * would be: return http_response_append_mem(r, BUF_PTR_LEN(mem)); */
+
+ if (r->resp_decode_chunked)
+ return http_chunk_decode_append_buffer(r, mem);
+
+ if (r->resp_body_scratchpad > 0) {
+ off_t len = (off_t)buffer_clen(mem);
+ r->resp_body_scratchpad -= len;
+ if (r->resp_body_scratchpad <= 0) {
+ r->resp_body_finished = 1;
+ if (r->resp_body_scratchpad < 0) {
+ /*(silently truncate if data exceeds Content-Length)*/
+ len += r->resp_body_scratchpad;
+ r->resp_body_scratchpad = 0;
+ buffer_truncate(mem, (uint32_t)len);
+ }
+ }
+ }
+ else if (0 == r->resp_body_scratchpad) {
+ /*(silently truncate if data exceeds Content-Length)*/
+ return 0;
+ }
+ return http_chunk_append_buffer(r, mem);
+}
+
+
+static int http_response_append_mem(request_st * const r, const char * const mem, size_t len) {
+ if (r->resp_decode_chunked)
+ return http_chunk_decode_append_mem(r, mem, len);
+
+ if (r->resp_body_scratchpad > 0) {
+ r->resp_body_scratchpad -= (off_t)len;
+ if (r->resp_body_scratchpad <= 0) {
+ r->resp_body_finished = 1;
+ if (r->resp_body_scratchpad < 0) {
+ /*(silently truncate if data exceeds Content-Length)*/
+ len = (size_t)(r->resp_body_scratchpad + (off_t)len);
+ r->resp_body_scratchpad = 0;
+ }
+ }
+ }
+ else if (0 == r->resp_body_scratchpad) {
+ /*(silently truncate if data exceeds Content-Length)*/
+ return 0;
+ }
+ return http_chunk_append_mem(r, mem, len);
+}
+
+
static int http_response_process_headers(request_st * const restrict r, http_response_opts * const restrict opts, char * const restrict s, const unsigned short hoff[8192], const int is_nph) {
int i = 1;
@@ -1056,7 +1108,11 @@ handler_t http_response_parse_headers(request_st * const r, http_response_opts *
}
if (blen > 0) {
- if (0 != http_chunk_decode_append_mem(r, bstart, blen))
+ /* modules which set opts->parse() (e.g. mod_ajp13, mod_fastcgi) must
+ * not pass buffer with excess data to this routine (and do not do so
+ * due to framing of response headers separately from response body) */
+ int rc = http_response_append_mem(r, bstart, blen);
+ if (__builtin_expect( (0 != rc), 0))
return HANDLER_ERROR;
}
@@ -1168,7 +1224,8 @@ handler_t http_response_read(request_st * const r, http_response_opts * const op
/* accumulate response in b until headers completed (or error) */
if (r->resp_body_started) buffer_clear(b);
} else {
- if (0 != http_chunk_decode_append_buffer(r, b)) {
+ int rc = http_response_append_buffer(r, b);
+ if (__builtin_expect( (0 != rc), 0)) {
/* error writing to tempfile;
* truncate response or send 500 if nothing sent yet */
return HANDLER_ERROR;