Bug 16134 - mod_deflate may lead to HTTP/1.1 400 responce when a request is absolutely correct
Summary: mod_deflate may lead to HTTP/1.1 400 responce when a request is absolutely co...
Status: CLOSED FIXED
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: mod_deflate (show other bugs)
Version: 2.0-HEAD
Hardware: PC Windows XP
: P3 major (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2003-01-15 20:19 UTC by Dmitri Dmitrienko
Modified: 2004-11-16 19:05 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dmitri Dmitrienko 2003-01-15 20:19:16 UTC
When following conditions are met, mod_deflate (as a filter) does not 
propagate EOS to the upper level and leads to WRONG REQUEST (HTTP 400) 
responce.
1. enable mod_dav, mod_dav_fs, mod_deflate
2. compression is enabled for both - input and output
3. client sends PROPFIND HTTP/1.1 request with Content-Encoding: gzip header 
and a properly gzip'ed xml content.

Example of httpd.conf:
###httpd.conf BEGIN
... skipped all common options ...

LoadModule deflate_module modules/mod_deflate.so
NameVirtualHost localhost:80
NameVirtualHost localhost:801
<VirtualHost localhost:80>
</VirtualHost>
<VirtualHost localhost:801>
    DAVLockDB logs/DavLock
    <Directory "D:/apa2_0_43_15JAN03/Debug/htdocs">
      SetInputFilter DEFLATE
      SetOutputFilter DEFLATE
      DAV On
      <Limit PUT POST DELETE PROPFIND PROPPATCH MKCOL COPY MOVE LOCK UNLOCK>
        AuthName             "Foo"
        AuthType             Basic
        AuthUserFile         logs/passw
        Require user dmitri
      </Limit>
    </Directory>
</VirtualHost>

###httpd.conf END

My investigation showed that the trouble is in xml_util.c and mod_delate.c 
files. First requires data until a len=0 (normal condition) or len<0 (error) 
returned while the second never returns EOS and as a result len is never 0.

See mod_deflate.c:662:
            /* If we actually see the EOS, that means we screwed up! */
            if (APR_BUCKET_IS_EOS(bkt)) {
                return APR_EGENERAL;
            }

I propose a patch that works:

--- mod_deflate.c~	2003-01-03 02:12:36.000000000 +0300
+++ mod_deflate.c	2003-01-15 23:15:38.000000000 +0300
@@ -648,6 +648,15 @@
         apr_brigade_cleanup(ctx->bb);
     }
 
+    if (APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(ctx->bb))) {
+        apr_bucket *eos;
+
+        apr_brigade_cleanup(ctx->bb);
+        eos = apr_bucket_eos_create(f->c->bucket_alloc);
+        APR_BRIGADE_INSERT_TAIL(bb, eos); 
+        return APR_SUCCESS;
+	}
+
     if (APR_BRIGADE_EMPTY(ctx->proc_bb)) {
         rv = ap_get_brigade(f->next, ctx->bb, mode, block, readbytes);
 

I'm not sure that it's absolutely correct and it needs to be reviewed by 
somebody who knows Apache2 architecture better.
Comment 1 Dmitri Dmitrienko 2003-01-15 20:35:56 UTC
Once again the proposed patch agains the most recent version of mod_deflate.c:

--- mod_deflate.c~	2003-01-03 02:12:36.000000000 +0300
+++ mod_deflate.c	2003-01-15 23:31:04.000000000 +0300
@@ -557,7 +557,7 @@
     int zRC;
     apr_status_t rv;
     deflate_filter_config *c;
-
+
     /* just get out of the way of things we don't want. */
     if (mode != AP_MODE_READBYTES) {
         return ap_get_brigade(f->next, bb, mode, block, readbytes);
@@ -655,6 +655,15 @@
             return rv;
         }
 
+		if (APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(ctx->bb))) {
+			apr_bucket *eos;
+
+			apr_brigade_cleanup(ctx->bb);
+			eos = apr_bucket_eos_create(f->c->bucket_alloc);
+			APR_BRIGADE_INSERT_TAIL(bb, eos); 
+			return APR_SUCCESS;
+		}
+
         APR_BRIGADE_FOREACH(bkt, ctx->bb) {
             const char *data;
             apr_size_t len;
Comment 2 Justin Erenkrantz 2003-02-17 06:16:30 UTC
Changed how ap_xml_parse_input works in server/util_xml.c r1.22 so that it realizes when EOS is sent.  I've proposed this to be backported to the next stable release.

Thanks for using Apache HTTP Server!