From 1c98aabbf13be673d386684d13e066139eed3c68 Mon Sep 17 00:00:00 2001 From: Ryan Bloom Date: Sun, 6 May 2001 23:27:14 +0000 Subject: [PATCH] Back out the recent change to ap_get_brigade, to make it use indirection again. The problem is that the amount of data read from the network, is not necessarily the amount of data returned from the filters. It is possible for input filters to add bytes to the data read from the network. To fix the original bug, I just removed the line from ap_get_client_block that decremented r->remaining, we allow the http_filter to do that for us. I have also removed an incorrect comment. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@89041 13f79535-47bb-0310-9956-ffa450edef68 --- include/util_filter.h | 4 ++-- modules/experimental/mod_case_filter_in.c | 2 +- modules/experimental/mod_charset_lite.c | 2 +- modules/experimental/mod_ext_filter.c | 2 +- modules/http/http_protocol.c | 21 ++++++++++----------- modules/http/http_request.c | 3 ++- modules/http/mod_core.h | 4 ++-- modules/mappers/mod_alias.c | 11 ++++++++++- modules/tls/mod_tls.c | 4 ++-- server/core.c | 10 +--------- server/mpm/experimental/perchild/perchild.c | 5 +++-- server/mpm/perchild/perchild.c | 5 +++-- server/protocol.c | 3 ++- server/util_filter.c | 2 +- 14 files changed, 41 insertions(+), 37 deletions(-) diff --git a/include/util_filter.h b/include/util_filter.h index 2ee93fa8ee..17e5c0acad 100644 --- a/include/util_filter.h +++ b/include/util_filter.h @@ -155,7 +155,7 @@ typedef struct ap_filter_t ap_filter_t; */ typedef apr_status_t (*ap_out_filter_func)(ap_filter_t *f, apr_bucket_brigade *b); typedef apr_status_t (*ap_in_filter_func)(ap_filter_t *f, apr_bucket_brigade *b, - ap_input_mode_t mode, apr_size_t readbytes); + ap_input_mode_t mode, apr_size_t *readbytes); typedef union ap_filter_func { ap_out_filter_func out_func; @@ -276,7 +276,7 @@ struct ap_filter_t { * a single line should be read. */ AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *filter, apr_bucket_brigade *bucket, - ap_input_mode_t mode, apr_size_t readbytes); + ap_input_mode_t mode, apr_size_t *readbytes); /** * Pass the current bucket brigade down to the next filter on the filter diff --git a/modules/experimental/mod_case_filter_in.c b/modules/experimental/mod_case_filter_in.c index e4ab97feab..94ecae6dd0 100644 --- a/modules/experimental/mod_case_filter_in.c +++ b/modules/experimental/mod_case_filter_in.c @@ -47,7 +47,7 @@ static void CaseFilterInInsertFilter(request_rec *r) static apr_status_t CaseFilterInFilter(ap_filter_t *f, apr_bucket_brigade *pbbOut, - ap_input_mode_t eMode,apr_size_t nBytes) + ap_input_mode_t eMode,apr_size_t *nBytes) { CaseFilterInContext *pCtx=f->ctx; apr_status_t ret; diff --git a/modules/experimental/mod_charset_lite.c b/modules/experimental/mod_charset_lite.c index 190ec1b4d3..79830eed08 100644 --- a/modules/experimental/mod_charset_lite.c +++ b/modules/experimental/mod_charset_lite.c @@ -1005,7 +1005,7 @@ static void transfer_brigade(apr_bucket_brigade *in, apr_bucket_brigade *out) } static int xlate_in_filter(ap_filter_t *f, apr_bucket_brigade *bb, - ap_input_mode_t mode, apr_size_t readbytes) + ap_input_mode_t mode, apr_size_t *readbytes) { apr_status_t rv; charset_req_t *reqinfo = ap_get_module_config(f->r->request_config, diff --git a/modules/experimental/mod_ext_filter.c b/modules/experimental/mod_ext_filter.c index 7f9d87b62c..46b4b1e527 100644 --- a/modules/experimental/mod_ext_filter.c +++ b/modules/experimental/mod_ext_filter.c @@ -749,7 +749,7 @@ static apr_status_t ef_output_filter(ap_filter_t *f, apr_bucket_brigade *bb) #if 0 static int ef_input_filter(ap_filter_t *f, apr_bucket_brigade *bb, - ap_input_mode_t mode, apr_size_t readbytes) + ap_input_mode_t mode, apr_size_t *readbytes) { apr_status_t rv; apr_bucket *b; diff --git a/modules/http/http_protocol.c b/modules/http/http_protocol.c index f092dbdbaf..95ace2ed16 100644 --- a/modules/http/http_protocol.c +++ b/modules/http/http_protocol.c @@ -424,7 +424,7 @@ struct dechunk_ctx { static long get_chunk_size(char *); apr_status_t ap_dechunk_filter(ap_filter_t *f, apr_bucket_brigade *bb, - ap_input_mode_t mode, apr_size_t readbytes) + ap_input_mode_t mode, apr_size_t *readbytes) { apr_status_t rv; struct dechunk_ctx *ctx = f->ctx; @@ -484,7 +484,7 @@ apr_status_t ap_dechunk_filter(ap_filter_t *f, apr_bucket_brigade *bb, apr_size_t chunk_bytes = ctx->chunk_size - ctx->bytes_delivered; if ((rv = ap_get_brigade(f->next, bb, mode, - chunk_bytes)) != APR_SUCCESS) { + &chunk_bytes)) != APR_SUCCESS) { return rv; } @@ -518,7 +518,7 @@ typedef struct http_filter_ctx { apr_bucket_brigade *b; } http_ctx_t; -apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t readbytes) +apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t *readbytes) { apr_bucket *e; char *buff; @@ -577,7 +577,7 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode } /* readbytes == 0 is "read a single line". otherwise, read a block. */ - if (readbytes) { + if (*readbytes) { /* ### the code below, which moves bytes from one brigade to the ### other is probably bogus. presuming the next filter down was @@ -604,12 +604,12 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode * a time - don't assume that one call to apr_bucket_read() * will return the full string. */ - if (readbytes < len) { - apr_bucket_split(e, readbytes); - readbytes = 0; + if (*readbytes < len) { + apr_bucket_split(e, *readbytes); + *readbytes = 0; } else { - readbytes -= len; + *readbytes -= len; } APR_BUCKET_REMOVE(e); APR_BRIGADE_INSERT_TAIL(b, e); @@ -628,7 +628,7 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode ### chunks to determine where the end of the request is, so we ### shouldn't be monkeying with EOS buckets. */ - if (readbytes == 0) { + if (*readbytes == 0) { apr_bucket *eos = apr_bucket_eos_create(); APR_BRIGADE_INSERT_TAIL(b, eos); @@ -1403,7 +1403,7 @@ AP_DECLARE(long) ap_get_client_block(request_rec *r, char *buffer, int bufsiz) do { if (APR_BRIGADE_EMPTY(bb)) { if (ap_get_brigade(r->input_filters, bb, AP_MODE_BLOCKING, - r->remaining) != APR_SUCCESS) { + &r->remaining) != APR_SUCCESS) { /* if we actually fail here, we want to just return and * stop trying to read data from the client. */ @@ -1449,7 +1449,6 @@ AP_DECLARE(long) ap_get_client_block(request_rec *r, char *buffer, int bufsiz) * these */ r->read_length += len_read; /* XXX yank me? */ - r->remaining -= len_read; /* XXX yank me? */ old = b; b = APR_BUCKET_NEXT(b); apr_bucket_delete(old); diff --git a/modules/http/http_request.c b/modules/http/http_request.c index d79f4c7987..a2a03827e4 100644 --- a/modules/http/http_request.c +++ b/modules/http/http_request.c @@ -367,6 +367,7 @@ static void check_pipeline_flush(request_rec *r) ### allow us to defer creation of the brigade to when we actually ### need to send a FLUSH. */ apr_bucket_brigade *bb = apr_brigade_create(r->pool); + int zero = 0; /* Flush the filter contents if: * @@ -376,7 +377,7 @@ static void check_pipeline_flush(request_rec *r) /* ### shouldn't this read from the connection input filters? */ /* ### is zero correct? that means "read one line" */ if (!r->connection->keepalive || - ap_get_brigade(r->input_filters, bb, AP_MODE_PEEK, 0) != APR_SUCCESS) { + ap_get_brigade(r->input_filters, bb, AP_MODE_PEEK, &zero) != APR_SUCCESS) { apr_bucket *e = apr_bucket_flush_create(); /* We just send directly to the connection based filters. At diff --git a/modules/http/mod_core.h b/modules/http/mod_core.h index 2f149797bf..f01f6a0f1f 100644 --- a/modules/http/mod_core.h +++ b/modules/http/mod_core.h @@ -74,9 +74,9 @@ extern "C" { * These (input) filters are internal to the mod_core operation. */ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, - ap_input_mode_t mode, apr_size_t readbytes); + ap_input_mode_t mode, apr_size_t *readbytes); apr_status_t ap_dechunk_filter(ap_filter_t *f, apr_bucket_brigade *b, - ap_input_mode_t mode, apr_size_t readbytes); + ap_input_mode_t mode, apr_size_t *readbytes); char *ap_response_code_string(request_rec *r, int error_index); diff --git a/modules/mappers/mod_alias.c b/modules/mappers/mod_alias.c index a5752e3c1e..5217ff373a 100644 --- a/modules/mappers/mod_alias.c +++ b/modules/mappers/mod_alias.c @@ -335,7 +335,16 @@ static char *try_alias_list(request_rec *r, apr_array_header_t *aliases, int doe found = ap_pregsub(r->pool, p->real, r->uri, p->regexp->re_nsub + 1, regm); if (found && doesc) { - found = ap_escape_uri(r->pool, found); + uri_components uri; + ap_parse_uri_components(r->pool, found, &uri); + found = ap_escape_uri(r->pool, uri.path); + if (uri.query) { + found = apr_pstrcat(r->pool, found, "?", uri.query, NULL); + } + else if (uri.fragment) { + found = apr_pstrcat(r->pool, found, "#", uri.fragment, NULL); + + } } } else { diff --git a/modules/tls/mod_tls.c b/modules/tls/mod_tls.c index 3f3130694b..de7f8ece2c 100644 --- a/modules/tls/mod_tls.c +++ b/modules/tls/mod_tls.c @@ -186,7 +186,7 @@ static apr_status_t churn_output(TLSFilterCtx *pCtx) return APR_SUCCESS; } -static apr_status_t churn(TLSFilterCtx *pCtx,apr_read_type_e eReadType,apr_size_t readbytes) +static apr_status_t churn(TLSFilterCtx *pCtx,apr_read_type_e eReadType,apr_size_t *readbytes) { ap_input_mode_t eMode=eReadType == APR_BLOCK_READ ? AP_MODE_BLOCKING : AP_MODE_NONBLOCKING; @@ -333,7 +333,7 @@ static apr_status_t tls_out_filter(ap_filter_t *f,apr_bucket_brigade *pbbIn) } static apr_status_t tls_in_filter(ap_filter_t *f,apr_bucket_brigade *pbbOut, - ap_input_mode_t eMode, apr_size_t readbytes) + ap_input_mode_t eMode, apr_size_t *readbytes) { TLSFilterCtx *pCtx=f->ctx; apr_read_type_e eReadType=eMode == AP_MODE_BLOCKING ? APR_BLOCK_READ : diff --git a/server/core.c b/server/core.c index b230fc974e..18661e1b93 100644 --- a/server/core.c +++ b/server/core.c @@ -2995,18 +2995,10 @@ static int default_handler(request_rec *r) return ap_pass_brigade(r->output_filters, bb); } -static int core_input_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t readbytes) +static int core_input_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t *readbytes) { apr_bucket *e; - /* ### we should obey readbytes. the policy is to not insert more than - ### READBYTES into the brigade. the caller knows the amount that is - ### proper for the protocol. reading more than that could cause - ### problems. - ### (of course, we can read them from the socket, we just should not - ### return them until asked) - */ - if (!f->ctx) { /* If we haven't passed up the socket yet... */ f->ctx = (void *)1; e = apr_bucket_socket_create(f->c->client_socket); diff --git a/server/mpm/experimental/perchild/perchild.c b/server/mpm/experimental/perchild/perchild.c index 4bad0ccdfd..a27ba5ecce 100644 --- a/server/mpm/experimental/perchild/perchild.c +++ b/server/mpm/experimental/perchild/perchild.c @@ -1362,6 +1362,7 @@ static int pass_request(request_rec *r) &mpm_perchild_module); char *foo; apr_size_t len; + int zero = 0; apr_pool_userdata_get((void **)&foo, "PERCHILD_BUFFER", r->connection->pool); len = strlen(foo); @@ -1401,7 +1402,7 @@ static int pass_request(request_rec *r) ### reading large chunks of data or something? */ while (ap_get_brigade(r->input_filters, bb, AP_MODE_NONBLOCKING, - 0 /* read one line */) == APR_SUCCESS) { + &zero /* read one line */) == APR_SUCCESS) { apr_bucket *e; APR_BRIGADE_FOREACH(e, bb) { const char *str; @@ -1495,7 +1496,7 @@ static int perchild_post_read(request_rec *r) return OK; } -static apr_status_t perchild_buffer(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t readbytes) +static apr_status_t perchild_buffer(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t *readbytes) { apr_bucket *e; apr_status_t rv; diff --git a/server/mpm/perchild/perchild.c b/server/mpm/perchild/perchild.c index 4bad0ccdfd..a27ba5ecce 100644 --- a/server/mpm/perchild/perchild.c +++ b/server/mpm/perchild/perchild.c @@ -1362,6 +1362,7 @@ static int pass_request(request_rec *r) &mpm_perchild_module); char *foo; apr_size_t len; + int zero = 0; apr_pool_userdata_get((void **)&foo, "PERCHILD_BUFFER", r->connection->pool); len = strlen(foo); @@ -1401,7 +1402,7 @@ static int pass_request(request_rec *r) ### reading large chunks of data or something? */ while (ap_get_brigade(r->input_filters, bb, AP_MODE_NONBLOCKING, - 0 /* read one line */) == APR_SUCCESS) { + &zero /* read one line */) == APR_SUCCESS) { apr_bucket *e; APR_BRIGADE_FOREACH(e, bb) { const char *str; @@ -1495,7 +1496,7 @@ static int perchild_post_read(request_rec *r) return OK; } -static apr_status_t perchild_buffer(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t readbytes) +static apr_status_t perchild_buffer(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t *readbytes) { apr_bucket *e; apr_status_t rv; diff --git a/server/protocol.c b/server/protocol.c index 0d816b835e..bd9d268c69 100644 --- a/server/protocol.c +++ b/server/protocol.c @@ -217,9 +217,10 @@ AP_CORE_DECLARE(int) ap_getline(char *s, int n, request_rec *r, int fold) while (1) { if (APR_BRIGADE_EMPTY(b)) { + int zero = 0; if ((retval = ap_get_brigade(c->input_filters, b, AP_MODE_BLOCKING, - 0 /* readline */)) != APR_SUCCESS || + &zero /* readline */)) != APR_SUCCESS || APR_BRIGADE_EMPTY(b)) { apr_brigade_destroy(b); return -1; diff --git a/server/util_filter.c b/server/util_filter.c index eaa3ad3f71..ef9a55262f 100644 --- a/server/util_filter.c +++ b/server/util_filter.c @@ -211,7 +211,7 @@ AP_DECLARE(void) ap_remove_output_filter(ap_filter_t *f) AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *next, apr_bucket_brigade *bb, ap_input_mode_t mode, - apr_size_t readbytes) + apr_size_t *readbytes) { if (next) { return next->frec->filter_func.in_func(next, bb, mode, readbytes);