From f8b65dcc52e68e914eb4e0a0596eabe3bf3d8fb1 Mon Sep 17 00:00:00 2001 From: Yann Ylavic Date: Thu, 27 Feb 2014 18:15:03 +0000 Subject: [PATCH] Commit 6 on 6 to fix reentrance (incomplete Zlib header or validation bytes) in mod_deflate's output and input filters. PR 46146 (patches from duplicated PR 55666) Ignore empty buckets and split buckets longer than INT_MAX (since zlib uses 32-bit ints only) in all filters. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1572671 13f79535-47bb-0310-9956-ffa450edef68 --- modules/filters/mod_deflate.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/modules/filters/mod_deflate.c b/modules/filters/mod_deflate.c index a50bc48fc82..1d48ddfc977 100644 --- a/modules/filters/mod_deflate.c +++ b/modules/filters/mod_deflate.c @@ -49,6 +49,8 @@ #include "zlib.h" +#include /* for INT_MAX */ + static const char deflateFilterName[] = "DEFLATE"; module AP_MODULE_DECLARE_DATA deflate_module; @@ -843,6 +845,14 @@ static apr_status_t deflate_out_filter(ap_filter_t *f, /* read */ apr_bucket_read(e, &data, &len, APR_BLOCK_READ); + if (!len) { + apr_bucket_delete(e); + continue; + } + if (len > INT_MAX) { + apr_bucket_split(e, INT_MAX); + apr_bucket_read(e, &data, &len, APR_BLOCK_READ); + } /* This crc32 function is from zlib. */ ctx->crc = crc32(ctx->crc, (const Bytef *)data, len); @@ -1187,6 +1197,13 @@ static apr_status_t deflate_in_filter(ap_filter_t *f, /* read */ apr_bucket_read(bkt, &data, &len, APR_BLOCK_READ); + if (!len) { + continue; + } + if (len > INT_MAX) { + apr_bucket_split(bkt, INT_MAX); + apr_bucket_read(bkt, &data, &len, APR_BLOCK_READ); + } if (ctx->zlib_flags) { rv = consume_zlib_flags(ctx, &data, &len); @@ -1200,7 +1217,7 @@ static apr_status_t deflate_in_filter(ap_filter_t *f, /* pass through zlib inflate. */ ctx->stream.next_in = (unsigned char *)data; - ctx->stream.avail_in = len; + ctx->stream.avail_in = (int)len; zRC = Z_OK; @@ -1533,6 +1550,14 @@ static apr_status_t inflate_out_filter(ap_filter_t *f, /* read */ apr_bucket_read(e, &data, &len, APR_BLOCK_READ); + if (!len) { + apr_bucket_delete(e); + continue; + } + if (len > INT_MAX) { + apr_bucket_split(e, INT_MAX); + apr_bucket_read(e, &data, &len, APR_BLOCK_READ); + } /* first bucket contains zlib header */ if (ctx->header_len < sizeof(ctx->header)) { -- 2.47.3