Description of problem: The user-defined variable in header included in the output from cgi program is not checked in mod_filter at all. test cgi program: --------------------------------------------------- #!/usr/bin/perl print "foo: bar=1024\n\n"; print "sample CGI\n"; --------------------------------------------------- And, /etc/httpd/conf.d/deflate.conf includes this: --------------------------------------------------- ... # Filter Settings LoadModule filter_module modules/mod_filter.so <Location /> FilterDeclare deflate CONTENT_SET FilterProvider deflate DEFLATE foo !bar=0 FilterChain deflate </Location> --------------------------------------------------- What is expected here is that the data sent from this httpd server is compressed, because 'bar' is 1024 (not 0). But, this is not compressed actually. As other examples with the same cgi program: 1) FilterProvider deflate DEFLATE foo bar=0 This is compressed. this is unexpected 2) FilterProvider deflate DEFLATE foo bar=1024 This is compressed. it's ok. 3) FilterProvider deflate DEFLATE foo bar=1025 This is compressed. this is unexpected. 4) FilterProvider deflate DEFLATE foo !bar=1024 This is not compressed. it's ok. 5) FilterProvider deflate DEFLATE foo !bar=1025 This is not compressed. unexpected. As we saw in this examples, in case of the negative condition, it's not compressed. It's not related with the value of the variable 'bar'. filter_harness() is called from cgi_handler() via ap_pass_brigade(), and it calls filter_lookup(). And, it searches the variable 'foo' in a table. case RESPONSE_HEADERS: str = apr_table_get(r->headers_out, provider->value); break; But, this always returns NULL. for (provider = filter->providers; provider; provider = provider->next) { match = 1; // NULL is set to str here. if (!str) { if (provider->match_type == DEFINED && provider->match.string) { match = 0; } } ... if (match != provider->not) { At this point, match is 1 and provider->not means if the condition is negative or positive. This is the reason why the test results depends on if the condition is negative. On the other hand, ap_add_common_vars() is called from cgi_handler(), and it registers some specific variable only in header to the table. Any user-defined variable in header are not registered to the table. Version-Release number of selected component (if applicable): Red Hat Enterprise Linux 5.6 httpd-2.2.3-45.el5 How reproducible: Always Steps to Reproduce: 1. Enable the deflating function with the following config file. /etc/httpd/conf.d/deflate.conf --------------------------------------------------- # Deflate Settings DeflateWindowSize 15 DeflateMemLevel 9 DeflateBufferSize 131072 DeflateCompressionLevel 9 DeflateFilterNote Input instream DeflateFilterNote Output outstream DeflateFilterNote Ratio ratio LogFormat '"%r" %{outstream}n/%{instream}n (%{ratio}n%%) %{User-agent}i' deflate CustomLog logs/deflate_log deflate # Filter Settings LoadModule filter_module modules/mod_filter.so <Location /> FilterDeclare deflate CONTENT_SET FilterProvider deflate DEFLATE foo !bar=0 FilterChain deflate </Location> --------------------------------------------------- 2. Create the following cgi file. /var/www/cgi-bin/test.cgi --------------------------------------------------- #!/usr/bin/perl print "foo: bar=1024\n\n"; print "sample CGI\n"; --------------------------------------------------- 3. service httpd start 4. telnet localhost 80 Trying 127.0.0.1... Connected to localhost.localdomain (127.0.0.1). Escape character is '^]'. GET /cgi-bin/test.cgi HTTP/1.1 Host: 127.0.0.1 User-Agent: MSIE Accept-Encoding: deflate,gzip <Please press "Enter" twice.> HTTP/1.1 200 OK Date: Fri, 10 Dec 2010 21:30:01 GMT Server: Apache/2.2.3 (Red Hat) foo: bar=1024 Content-Length: 11 Connection: close Content-Type: text/plain; charset=UTF-8 sample CGI Connection closed by foreign host. Actual results: The data is not compressed Expected results: The data is compressed Additional info: In case of the following php program, it's compressed properly. /var/www/cgi-bin/test.php --------------------------------------------------- <?php header('foo: bar=1024'); ?> sample PHP --------------------------------------------------- Because the user-defined variables in header are registered to the table (which is checked in mod_filter) properly in php_handler().
Thanks for the report and patch. Changing core behaviour for this is not necessary; we merely need to get mod_filter to check r->err_headers_out as well as r->headers_out for a response header match. i.e. str = apr_table_get(r->headers_out, provider->value); if (str == NULL) { str = apr_table_get(r->err_headers_out, provider->value); }
Fixed upstream: http://svn.apache.org/viewvc?view=revision&revision=1090234
An advisory has been issued which should help the problem described in this bug report. This report is therefore being closed with a resolution of ERRATA. For more information on therefore solution and/or where to find the updated files, please follow the link below. You may reopen this bug report if the solution does not work for you. http://rhn.redhat.com/errata/RHBA-2011-1067.html