From 44b8351ffdaeddab23c4188d2c7a93515f4536aa Mon Sep 17 00:00:00 2001 From: Graham Leggett Date: Tue, 21 May 2013 15:10:46 +0000 Subject: [PATCH] mod_deflate: Remove assumptions as to when an EOS bucket might arrive. Gracefully step aside if the body size is zero. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1484832 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 3 +++ modules/filters/mod_deflate.c | 44 ++++++++++++++++++++++++++--------- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/CHANGES b/CHANGES index c4709deb5e..074d828051 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ -*- coding: utf-8 -*- Changes with Apache 2.5.0 + *) mod_deflate: Remove assumptions as to when an EOS bucket might arrive. + Gracefully step aside if the body size is zero. [Graham Leggett] + *) 'AuthGroupFile' and 'AuthUserFile' do not accept anymore the optional 'standard' keyword . It was unused and not documented. PR54463 [Tianyin Xu and Christophe Jaillet] diff --git a/modules/filters/mod_deflate.c b/modules/filters/mod_deflate.c index 48d37b1392..cb479f15a4 100644 --- a/modules/filters/mod_deflate.c +++ b/modules/filters/mod_deflate.c @@ -304,8 +304,9 @@ typedef struct deflate_ctx_t int (*libz_end_func)(z_streamp); unsigned char *validation_buffer; apr_size_t validation_buffer_length; - int inflate_init; - int filter_init; + unsigned int inflate_init:1; + unsigned int filter_init:1; + unsigned int done:1; } deflate_ctx; /* Number of validation bytes (CRC and length) after the compressed data */ @@ -942,6 +943,13 @@ static apr_status_t deflate_in_filter(ap_filter_t *f, return rv; } + /* zero length body? step aside */ + bkt = APR_BRIGADE_FIRST(ctx->bb); + if (APR_BUCKET_IS_EOS(bkt)) { + ap_remove_input_filter(f); + return ap_get_brigade(f->next, bb, mode, block, readbytes); + } + apr_table_unset(r->headers_in, "Content-Length"); apr_table_unset(r->headers_in, "Content-MD5"); @@ -1002,12 +1010,19 @@ static apr_status_t deflate_in_filter(ap_filter_t *f, const char *data; apr_size_t len; - /* If we actually see the EOS, that means we screwed up! */ if (APR_BUCKET_IS_EOS(bkt)) { - inflateEnd(&ctx->stream); - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01390) - "Encountered EOS bucket in inflate filter (bug?)"); - return APR_EGENERAL; + if (!ctx->done) { + inflateEnd(&ctx->stream); + ap_log_rerror( + APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02481) "Encountered premature end-of-stream while inflating"); + return APR_EGENERAL; + } + + /* Move everything to the returning brigade. */ + APR_BUCKET_REMOVE(bkt); + APR_BRIGADE_INSERT_TAIL(ctx->proc_bb, bkt); + ap_remove_input_filter(f); + break; } if (APR_BUCKET_IS_FLUSH(bkt)) { @@ -1036,6 +1051,13 @@ static apr_status_t deflate_in_filter(ap_filter_t *f, break; } + /* sanity check - data after completed compressed body and before eos? */ + if (ctx->done) { + ap_log_rerror( + APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02482) "Encountered extra data after compressed data"); + return APR_EGENERAL; + } + /* read */ apr_bucket_read(bkt, &data, &len, APR_BLOCK_READ); @@ -1073,7 +1095,7 @@ static apr_status_t deflate_in_filter(ap_filter_t *f, } } if (zRC == Z_STREAM_END) { - apr_bucket *tmp_heap, *eos; + apr_bucket *tmp_heap; ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01393) "Zlib: Inflated %ld to %ld : URL %s", @@ -1120,8 +1142,7 @@ static apr_status_t deflate_in_filter(ap_filter_t *f, inflateEnd(&ctx->stream); - eos = apr_bucket_eos_create(f->c->bucket_alloc); - APR_BRIGADE_INSERT_TAIL(ctx->proc_bb, eos); + ctx->done = 1; break; } @@ -1356,7 +1377,8 @@ static apr_status_t inflate_out_filter(ap_filter_t *f, apr_bucket_read(e, &data, &len, APR_BLOCK_READ); /* first bucket contains zlib header */ - if (!ctx->inflate_init++) { + if (!ctx->inflate_init) { + ctx->inflate_init = 1; if (len < 10) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01403) "Insufficient data for inflate"); -- 2.40.0