]> granicus.if.org Git - apache/commitdiff
* As reads might have morphed the bucket and its length read until we reached
authorRuediger Pluem <rpluem@apache.org>
Thu, 25 Aug 2011 14:27:09 +0000 (14:27 +0000)
committerRuediger Pluem <rpluem@apache.org>
Thu, 25 Aug 2011 14:27:09 +0000 (14:27 +0000)
  the correct bucket for splitting.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1161573 13f79535-47bb-0310-9956-ffa450edef68

modules/http/byterange_filter.c

index 3cc5cf202f5c63ba8d3d731560cd776748beb231..9a375dd067040f26b93e521dc17491e0ea02dc19 100644 (file)
@@ -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;
         }