From: Brian Pane Date: Fri, 21 Dec 2001 04:21:15 +0000 (+0000) Subject: Fixed a bug in ap_rgetline() X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a127066202022b32a2821ae3386d6f34b2f9b0f6;p=apache Fixed a bug in ap_rgetline() When an input line required more than one read, each subsequent block of data was copied on top of the previous one. So if a request line got split into multiple packets, the data would be corrupted. The new code uses a power-of-two allocator to expand the buffer and properly append the next block of data at the end of the previous one. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@92558 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/server/protocol.c b/server/protocol.c index 50cd1ed962..d4e225bef7 100644 --- a/server/protocol.c +++ b/server/protocol.c @@ -204,12 +204,14 @@ AP_DECLARE(int) ap_rgetline(char **s, int n, request_rec *r, int fold) char *last_char; const char *temp; int retval; - int total = 0; + apr_size_t total = 0; int looking_ahead = 0; apr_size_t length; core_request_config *req_cfg; apr_bucket_brigade *b; apr_bucket *e; + int do_alloc = (*s == NULL); + apr_size_t alloc_size = 0; req_cfg = (core_request_config *) ap_get_module_config(r->request_config, &core_module); @@ -257,11 +259,25 @@ AP_DECLARE(int) ap_rgetline(char **s, int n, request_rec *r, int fold) AP_DEBUG_ASSERT(!APR_BRIGADE_EMPTY(req_cfg->bb)); break; } - if (total + (int)length - 1 < n) { - if (!*s) { - *s = apr_palloc(r->pool, length + 2); /* +2 for LF, null */ + if (total + length - 1 < (apr_size_t)n) { + if (do_alloc) { + if (!*s) { + alloc_size = length; + *s = apr_palloc(r->pool, length + 2); /* +2 for LF, null */ + } + else if (total + length > alloc_size) { + apr_size_t new_size = alloc_size; + char *new_buffer; + do { + new_size *= 2; + } while (total + length > new_size); + new_buffer = apr_palloc(r->pool, new_size + 2); + memcpy(new_buffer, *s, total); + alloc_size = new_size; + *s = new_buffer; + } } - pos = *s; + pos = *s + total; last_char = pos + length - 1; memcpy(pos, temp, length); apr_bucket_delete(e);