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);
}
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;
}