httpd-bugs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
Subject DO NOT REPLY [Bug 49328] New: mod_filter mishandles contexts in subrequests, corrupt output with mod_deflate and mod_include
Date Sun, 23 May 2010 04:37:23 GMT

           Summary: mod_filter mishandles contexts in subrequests, corrupt
                    output with mod_deflate and mod_include
           Product: Apache httpd-2
           Version: 2.2.14
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: mod_filter

Created an attachment (id=25472)
 --> (
Prevent filter_init in mod_filter from destroying it's own harness context

Currently, mod_filter can't be used as a harness for mod_deflate when a 
subrequest may be initiated, specifically from mod_include.  Attempting to 
do so causes data in the response to be lost and/or sent uncompressed even
though the Content-Encoding header specifies a "gzip" encoding.

I originally thought this was related to bug 17629, and comments on that 
bug which describe similar symptoms indicate that many others do, too.  
However, the solution I proposed for this issue failed to address the 
original problem described in that bug, so I no longer think they are related.
I don't believe this is related to bug 43939 either, as mod_filter wasn't being 
used in that case.  A repeatable example of this issue follows.

The httpd configuration loads mod_filter and mod_include and contains these 

AddType text/html .shtml
AddOutputFilter INCLUDES .shtml

FilterDeclare smart_compress CONTENT_SET
FilterProvider smart_compress DEFLATE resp=Content-Type $text/
FilterChain smart_compress

Contents of example.shtml:

Included text below line
<HR />
<!--#include virtual="/includeme.shtml"-->

Contents of includeme.shtml:

This text was included


( echo 'GET /example.shtml HTTP/1.1' ; \
         echo 'Host: localhost' ; \
         echo 'Accept-Encoding: gzip' ; \
         echo '' ) | nc localhost 3080


HTTP/1.1 200 OK
Date: Sun, 23 May 2010 03:01:39 GMT
Server: Apache/2.2.14 (Unix)
Accept-Ranges: bytes
Vary: Accept-Encoding
Content-Encoding: gzip
Transfer-Encoding: chunked
Content-Type: text/html

This text was included




Output should be (as viewed in less):

HTTP/1.1 200 OK
Date: Sun, 23 May 2010 03:05:12 GMT
Server: Apache/2.2.14 (Unix)
Last-Modified: Sun, 23 May 2010 02:51:50 GMT
ETag: "2cb08c0-68-4873a01821d80"
Accept-Ranges: bytes
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 105
Content-Type: text/html


mod_filter appears to be the only module that uses the filter_init_func field
of the ap_filter_rec_t structure.  This member is a pointer to function that is
to be run right after the insert_filter hooks are run and right before the
content handler is invoked.  As most modules do their initialization at the
time they are called to process data, this feature is largely unused.  However,
mod_filter chooses to do its initialization here  so that it can correctly call
the filter_init_func of each provider if it exists.  

mod_filter sets filter_init_func to be a pointer to its filter_init function. 
In filter_init, it first creates the context for the harness, before calling
filter_init_func of each provider.  The initial context for each provider and
the ongoing context of the subsequently invoked provider are all stored in the
harness context.

The problem arises in that mod_filter intuitively assumes that filter_init will
only ever be called once during the lifetime of the filter harness.  However,
when mod_include creates a subrequest, all of the filters from the main request
get copied into the subrequest.  Before the content handler is invoked in the
subrequest, the filter_init_func of every filter in the subrequest gets called.
 This means that the filter_init_func of the filter harness gets called again,
one addition time for each subrequest.

The first thing that mod_filter does in filter_init is to assign the context
pointer to freshly allocated memory.  When called more than once, this
essentially destroys the existing harness context and any provider contexts
that it contains.  In the case of mod_deflate, it loses any data waiting in the
compression buffer.  Furthermore, when mod_deflate is invoked again without a
context, it assumes it is being called for the first time in that request. 
When it sees that Content-Encoding is already set to gzip, it removes itself
from the filter chain, leaving the remaining output uncompressed.

I don't know if it's considered correct or ideal operation that
filter_init_func can be called more than once, but as it stands, mod_filter
can't assume that it doesn't.  I am attaching a small patch that will make
filter_init first check for an existing harness context, simply returning if it
finds one already exists. I tested this patch with 2.2.14.

Configure bugmail:
------- You are receiving this mail because: -------
You are the assignee for the bug.
To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message