From: Ruediger Pluem Date: Thu, 25 Aug 2011 14:27:09 +0000 (+0000) Subject: * As reads might have morphed the bucket and its length read until we reached X-Git-Tag: 2.3.15~361 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=333325277031be7d584d5af09624936267d4dab1;p=thirdparty%2Fapache%2Fhttpd.git * As reads might have morphed the bucket and its length read until we reached the correct bucket for splitting. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1161573 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/http/byterange_filter.c b/modules/http/byterange_filter.c index 3cc5cf202f5..9a375dd0670 100644 --- a/modules/http/byterange_filter.c +++ b/modules/http/byterange_filter.c @@ -208,11 +208,39 @@ static apr_status_t copy_brigade_range(apr_bucket_brigade *bb, apr_brigade_cleanup(bbout); return rv; } - rv = apr_bucket_split(copy, (apr_size_t)(start64 - off_first)); - if (rv != APR_SUCCESS) { + /* + * The read above might have morphed copy in a bucket + * of shorter length. So read and delete until we reached + * the correct bucket for splitting. + */ + while (start64 - off_first > (apr_uint64_t)copy->length) { + apr_bucket *tmp; + + tmp = APR_BUCKET_NEXT(copy); + off_first += (apr_uint64_t)copy->length; + APR_BUCKET_REMOVE(copy); + apr_bucket_destroy(copy); + copy = tmp; + rv = apr_bucket_read(copy, &s, &len, APR_BLOCK_READ); + if (rv != APR_SUCCESS) { + apr_brigade_cleanup(bbout); + return rv; + } + } + if (start64 > off_first) { + rv = apr_bucket_split(copy, (apr_size_t)(start64 - off_first)); + if (rv != APR_SUCCESS) { + apr_brigade_cleanup(bbout); + return rv; + } + } + else { + copy = APR_BUCKET_PREV(copy); + } + } + else if (rv != APR_SUCCESS) { apr_brigade_cleanup(bbout); return rv; - } } out_first = APR_BUCKET_NEXT(copy); APR_BUCKET_REMOVE(copy); @@ -232,13 +260,43 @@ static apr_status_t copy_brigade_range(apr_bucket_brigade *bb, } if (end64 - off_last != (apr_uint64_t)e->length) { rv = apr_bucket_split(copy, (apr_size_t)(end64 + 1 - off_last)); - if (rv != APR_SUCCESS) { - apr_brigade_cleanup(bbout); - return rv; + if (rv == APR_ENOTIMPL) { + rv = apr_bucket_read(copy, &s, &len, APR_BLOCK_READ); + if (rv != APR_SUCCESS) { + apr_brigade_cleanup(bbout); + return rv; + } + /* + * The read above might have morphed copy in a bucket + * of shorter length. So read until we reached + * the correct bucket for splitting. + */ + while (end64 + 1 - off_last > (apr_uint64_t)copy->length) { + off_last += (apr_uint64_t)copy->length; + copy = APR_BUCKET_NEXT(copy); + rv = apr_bucket_read(copy, &s, &len, APR_BLOCK_READ); + if (rv != APR_SUCCESS) { + apr_brigade_cleanup(bbout); + return rv; + } + } + if (end64 < off_last + (apr_uint64_t)copy->length - 1) { + rv = apr_bucket_split(copy, end64 + 1 - off_last); + if (rv != APR_SUCCESS) { + apr_brigade_cleanup(bbout); + return rv; + } + } + } + else if (rv != APR_SUCCESS) { + apr_brigade_cleanup(bbout); + return rv; } copy = APR_BUCKET_NEXT(copy); - APR_BUCKET_REMOVE(copy); - apr_bucket_destroy(copy); + if (copy != APR_BRIGADE_SENTINEL(bbout)) { + APR_BUCKET_REMOVE(copy); + apr_bucket_destroy(copy); + } } break; }