#! /bin/sh /usr/share/dpatch/dpatch-run
## 085_CVE-2011-3192_regression_part2.dpatch by Steve Beattie <sbeattie@ubuntu.com>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: Additional fixes introduced by CVE-2011-3192 fix
# Subject: fix additional regressions introduced by CVE-2011-3192 patch
# Origin: upstream, patched through http://svn.apache.org/viewvc?view=revision&revision=1165607
#   + missing portiong of http://svn.apache.org/viewvc?view=revision&revision=1177080
#
# This patch fixes additional regressions in the byte-range behaviors
# introduced by the previous fix to CVE-2011-3192. It includes all the
# fixes up to the 2.2.21 release with the exception of the added MaxRanges
# directive. It also includes one fix staged for 2.2.22. --sbeattie
#
@DPATCH@
diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' apache2-2.2.17~/modules/http/byterange_filter.c apache2-2.2.17/modules/http/byterange_filter.c
--- apache2-2.2.17~/modules/http/byterange_filter.c	2011-11-02 15:24:58.000000000 -0700
+++ apache2-2.2.17/modules/http/byterange_filter.c	2011-11-02 15:30:41.000000000 -0700
@@ -83,8 +83,6 @@
     apr_bucket *first = NULL, *last = NULL, *out_first = NULL, *e;
     apr_uint64_t pos = 0, off_first = 0, off_last = 0;
     apr_status_t rv;
-    const char *s;
-    apr_size_t len;
     apr_uint64_t start64, end64;
     apr_off_t pofft = 0;
 
@@ -136,48 +134,9 @@
         if (e == first) {
             if (off_first != start64) {
                 rv = apr_bucket_split(copy, (apr_size_t)(start64 - off_first));
-                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 and delete until we reached
-                     * the correct bucket for splitting.
-                     */
-                    while (start64 - off_first > (apr_uint64_t)copy->length) {
-                        apr_bucket *tmp;
-                        int i = 0;
-                        if (i++ >= 99999)
-                            return APR_EINVAL;
-
-                        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;
+                if (rv != APR_SUCCESS) {
+                    apr_brigade_cleanup(bbout);
+                    return rv;
                 }
                 out_first = APR_BUCKET_NEXT(copy);
                 APR_BUCKET_REMOVE(copy);
@@ -194,37 +153,9 @@
             }
             if (end64 - off_last != (apr_uint64_t)e->length) {
                 rv = apr_bucket_split(copy, (apr_size_t)(end64 + 1 - off_last));
-                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;
+                if (rv != APR_SUCCESS) {
+                    apr_brigade_cleanup(bbout);
+                    return rv;
                 }
                 copy = APR_BUCKET_NEXT(copy);
                 if (copy != APR_BRIGADE_SENTINEL(bbout)) {
@@ -280,8 +211,8 @@
     char *bound_head = NULL;
     apr_array_header_t *indexes;
     indexes_t *idx;
-    int original_status;
     int i;
+    int original_status;
 
     /*
      * Iterate through the brigade until reaching EOS or a bucket with
@@ -325,7 +256,7 @@
         /* Is ap_make_content_type required here? */
         const char *orig_ct = ap_make_content_type(r, r->content_type);
         boundary = apr_psprintf(r->pool, "%" APR_UINT64_T_HEX_FMT "%lx",
-                                (apr_uint64_t)r->request_time, (long) getpid());
+                                (apr_uint64_t)r->request_time, c->id);
 
         ap_set_content_type(r, apr_pstrcat(r->pool, "multipart",
                                            use_range_x(r) ? "/x-" : "/",
@@ -392,7 +323,7 @@
         }
 
         APR_BRIGADE_CONCAT(bsend, tmpbb);
-        if (i && i % 32 == 0) {
+        if (i && !(i & 0x1F)) {
             /*
              * Every now and then, pass what we have down the filter chain.
              * In this case, the content-length filter cannot calculate and
@@ -513,8 +444,8 @@
         char *errp;
         apr_off_t number, start, end;
 
-	if (!*cur)
-	    break;
+        if (!*cur)
+            break;
 
         /*
          * Per RFC 2616 14.35.1: If there is at least one syntactically invalid
@@ -525,11 +456,14 @@
             return 0;
         }
 
-        if (dash == range) {
+        if (dash == cur) {
             /* In the form "-5" */
             if (apr_strtoff(&number, dash+1, &errp, 10) || *errp) {
                 return 0;
             }
+            if (number < 1) {
+                return 0;
+            }
             start = clength - number;
             end = clength - 1;
         }
@@ -550,6 +484,20 @@
             }
             else {                  /* "5-" */
                 end = clength - 1;
+                /*
+                 * special case: 0-
+                 *   ignore all other ranges provided
+                 *   return as a single range: 0-
+                 */
+                if (start == 0) {
+                    apr_array_clear(*indexes);
+                    idx = (indexes_t *)apr_array_push(*indexes);
+                    idx->start = start;
+                    idx->end = end;
+                    sum_lengths = clength;
+                    num_ranges = 1;
+                    break;
+                }
             }
         }
 
@@ -574,7 +522,6 @@
 
     if (num_ranges == 0 && unsatisfiable) {
         /* If all ranges are unsatisfiable, we should return 416 */
-        	ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "0U");
         return -1;
     }
     if (sum_lengths > clength) {
