From: Justin Erenkrantz Date: Mon, 17 Feb 2003 06:12:42 +0000 (+0000) Subject: Rework ap_xml_parse_input to work with bucket brigades rather than doing all X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=451d1ffea07350bf205835291b59550aa68c1de3;p=apache Rework ap_xml_parse_input to work with bucket brigades rather than doing all of the unneeded copying associated with ap_get_client_block. PR: 16134 git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@98691 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index efd09d4d5b..6847faa176 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,9 @@ Changes with Apache 2.1.0-dev [Remove entries to the current 2.0 section below, when backported] + *) Rewrite ap_xml_parse_input to use bucket brigades. PR 16134. + [Justin Erenkrantz] + *) Fix potential memory leaks in mod_deflate on malformed data. PR 16046. [Justin Erenkrantz] diff --git a/server/util_xml.c b/server/util_xml.c index ec659e102a..4e3bef25d4 100644 --- a/server/util_xml.c +++ b/server/util_xml.c @@ -69,31 +69,49 @@ AP_DECLARE(int) ap_xml_parse_input(request_rec * r, apr_xml_doc **pdoc) { apr_xml_parser *parser; - int result; + apr_bucket_brigade *brigade; + int result, seen_eos; apr_status_t status; char errbuf[200]; - - if ((result = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)) != OK) - return result; - - if (r->remaining == 0) { - *pdoc = NULL; - return OK; - } + apr_size_t total_read = 0; + apr_size_t limit_xml_body = ap_get_limit_xml_body(r); parser = apr_xml_parser_create(r->pool); + brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc); - if (ap_should_client_block(r)) { - long len; - char *buffer; - apr_size_t total_read = 0; - apr_size_t limit_xml_body = ap_get_limit_xml_body(r); + seen_eos = 0; + total_read = 0; - /* allocate our working buffer */ - buffer = apr_palloc(r->pool, READ_BLOCKSIZE); + do { + apr_bucket *bucket; /* read the body, stuffing it into the parser */ - while ((len = ap_get_client_block(r, buffer, READ_BLOCKSIZE)) > 0) { + status = ap_get_brigade(r->input_filters, brigade, + AP_MODE_READBYTES, APR_BLOCK_READ, + READ_BLOCKSIZE); + + if (status != APR_SUCCESS) { + goto read_error; + } + + APR_BRIGADE_FOREACH(bucket, brigade) { + const char *data; + apr_size_t len; + + if (APR_BUCKET_IS_EOS(bucket)) { + seen_eos = 1; + break; + } + + if (APR_BUCKET_IS_METADATA(bucket)) { + continue; + } + + status = apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ); + if (status != APR_SUCCESS) { + goto read_error; + } + total_read += len; if (limit_xml_body && total_read > limit_xml_body) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, @@ -102,15 +120,16 @@ AP_DECLARE(int) ap_xml_parse_input(request_rec * r, apr_xml_doc **pdoc) goto read_error; } - status = apr_xml_parser_feed(parser, buffer, len); - if (status) + status = apr_xml_parser_feed(parser, data, len); + if (status) { goto parser_error; + } } - if (len == -1) { - /* ap_get_client_block() has logged an error */ - goto read_error; - } - } + + apr_brigade_cleanup(brigade); + } while (!seen_eos); + + apr_brigade_destroy(brigade); /* tell the parser that we're done */ status = apr_xml_parser_done(parser, pdoc); @@ -133,6 +152,8 @@ AP_DECLARE(int) ap_xml_parse_input(request_rec * r, apr_xml_doc **pdoc) /* make sure the parser is terminated */ (void) apr_xml_parser_done(parser, NULL); + apr_brigade_destroy(brigade); + /* Apache will supply a default error, plus the error log above. */ return HTTP_BAD_REQUEST; }