Index: mod_deflate.c =================================================================== --- mod_deflate.c (revision 1562088) +++ mod_deflate.c (working copy) @@ -937,6 +937,8 @@ ctx->bb = apr_brigade_create(r->pool, f->c->bucket_alloc); ctx->proc_bb = apr_brigade_create(r->pool, f->c->bucket_alloc); ctx->buffer = apr_palloc(r->pool, c->bufferSize); + ctx->validation_buffer = NULL; + ctx->validation_buffer_length = 0; rv = ap_get_brigade(f->next, ctx->bb, AP_MODE_READBYTES, block, 10); if (rv != APR_SUCCESS) { @@ -1051,111 +1053,117 @@ 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); - /* pass through zlib inflate. */ - ctx->stream.next_in = (unsigned char *)data; - ctx->stream.avail_in = len; + if (!ctx->done) { - zRC = Z_OK; + /* pass through zlib inflate. */ + ctx->stream.next_in = (unsigned char *)data; + ctx->stream.avail_in = len; - while (ctx->stream.avail_in != 0) { - if (ctx->stream.avail_out == 0) { - apr_bucket *tmp_heap; - ctx->stream.next_out = ctx->buffer; - len = c->bufferSize - ctx->stream.avail_out; + zRC = Z_OK; - ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len); - tmp_heap = apr_bucket_heap_create((char *)ctx->buffer, len, - NULL, f->c->bucket_alloc); - APR_BRIGADE_INSERT_TAIL(ctx->proc_bb, tmp_heap); - ctx->stream.avail_out = c->bufferSize; - } + while (ctx->stream.avail_in != 0) { + if (ctx->stream.avail_out == 0) { + apr_bucket *tmp_heap; + ctx->stream.next_out = ctx->buffer; + len = c->bufferSize - ctx->stream.avail_out; - zRC = inflate(&ctx->stream, Z_NO_FLUSH); + ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len); + tmp_heap = apr_bucket_heap_create((char *)ctx->buffer, len, + NULL, f->c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(ctx->proc_bb, tmp_heap); + ctx->stream.avail_out = c->bufferSize; + } - if (zRC == Z_STREAM_END) { - break; - } + zRC = inflate(&ctx->stream, Z_NO_FLUSH); - if (zRC != Z_OK) { - inflateEnd(&ctx->stream); - ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01392) - "Zlib error %d inflating data (%s)", zRC, - ctx->stream.msg); - return APR_EGENERAL; - } - } - if (zRC == Z_STREAM_END) { - apr_bucket *tmp_heap; - apr_size_t avail; + if (zRC == Z_STREAM_END) { + break; + } - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01393) - "Zlib: Inflated %ld to %ld : URL %s", - ctx->stream.total_in, ctx->stream.total_out, - r->uri); + if (zRC != Z_OK) { + inflateEnd(&ctx->stream); + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01392) + "Zlib error %d inflating data (%s)", zRC, + ctx->stream.msg); + return APR_EGENERAL; + } + } + if (zRC == Z_STREAM_END) { + apr_bucket *tmp_heap; + apr_size_t avail; - len = c->bufferSize - ctx->stream.avail_out; + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01393) + "Zlib: Inflated %ld to %ld : URL %s", + ctx->stream.total_in, ctx->stream.total_out, + r->uri); - ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len); - tmp_heap = apr_bucket_heap_create((char *)ctx->buffer, len, - NULL, f->c->bucket_alloc); - APR_BRIGADE_INSERT_TAIL(ctx->proc_bb, tmp_heap); - ctx->stream.avail_out = c->bufferSize; + len = c->bufferSize - ctx->stream.avail_out; - avail = ctx->stream.avail_in; + ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len); + tmp_heap = apr_bucket_heap_create((char *)ctx->buffer, len, + NULL, f->c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(ctx->proc_bb, tmp_heap); + ctx->stream.avail_out = c->bufferSize; - /* Is the remaining 8 bytes already in the avail stream? */ - if (avail >= 8) { - unsigned long compCRC, compLen; - compCRC = getLong(ctx->stream.next_in); - if (ctx->crc != compCRC) { - inflateEnd(&ctx->stream); - ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01394) - "Zlib: CRC error inflating data"); - return APR_EGENERAL; + avail = ctx->stream.avail_in; + + /* Is the remaining 8 bytes already in the avail stream? */ + if (avail >= VALIDATION_SIZE) { + ctx->validation_buffer = ctx->stream.next_in; + ctx->validation_buffer_length = avail; + len = avail - VALIDATION_SIZE; + } + else { + ctx->validation_buffer = apr_pcalloc(f->r->pool, VALIDATION_SIZE); + memcpy(ctx->validation_buffer + ctx->validation_buffer_length, ctx->stream.next_in, avail); + ctx->validation_buffer_length = avail; + len = 0; + } + + inflateEnd(&ctx->stream); + ctx->done = 1; } - ctx->stream.next_in += 4; - compLen = getLong(ctx->stream.next_in); - if (ctx->stream.total_out != compLen) { - inflateEnd(&ctx->stream); - ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01395) - "Zlib: Length %ld of inflated data does " - "not match expected value %ld", - ctx->stream.total_out, compLen); - return APR_EGENERAL; - } } - else { - /* FIXME: We need to grab the 8 verification bytes - * from the wire! */ - inflateEnd(&ctx->stream); - ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01396) - "Verification data not available (bug?)"); - return APR_EGENERAL; - } - inflateEnd(&ctx->stream); + if (ctx->done) { + + /* Check verification bytes */ + if (ctx->validation_buffer_length) { + /* Did we have trailing data behind the closing 8 bytes? */ + if (ctx->validation_buffer_length + len > VALIDATION_SIZE) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02485) + "Encountered extra data after compressed data"); + return APR_EGENERAL; + } + if (len) { + memcpy(ctx->validation_buffer + ctx->validation_buffer_length,data,len); + ctx->validation_buffer_length += len; + } + } - ctx->done = 1; - - /* Did we have trailing data behind the closing 8 bytes? */ - if (avail > 8) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02485) - "Encountered extra data after compressed data"); - return APR_EGENERAL; + if (ctx->validation_buffer_length == VALIDATION_SIZE) { + unsigned long compCRC, compLen; + compCRC = getLong(ctx->validation_buffer); + if (ctx->crc != compCRC) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01394) + "Zlib: CRC error inflating data"); + return APR_EGENERAL; + } + ctx->validation_buffer += 4; + compLen = getLong(ctx->validation_buffer); + if (ctx->stream.total_out != compLen) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01395) + "Zlib: Length %ld of inflated data does " + "not match expected value %ld", + ctx->stream.total_out, compLen); + return APR_EGENERAL; + } + } } - } - - } + } apr_brigade_cleanup(ctx->bb); }