int windowSize;
int memlevel;
int compressionlevel;
- apr_size_t bufferSize;
+ int bufferSize;
const char *note_ratio_name;
const char *note_input_name;
const char *note_output_name;
return "DeflateBufferSize should be positive";
}
- c->bufferSize = (apr_size_t)n;
+ c->bufferSize = n;
return NULL;
}
/* Do update ctx->crc, see comment in flush_libz_buffer */
#define UPDATE_CRC 1
+static void consume_buffer(deflate_ctx *ctx, deflate_filter_config *c,
+ int len, int crc, apr_bucket_brigade *bb)
+{
+ apr_bucket *b;
+
+ /*
+ * Do we need to update ctx->crc? Usually this is the case for
+ * inflate action where we need to do a crc on the output, whereas
+ * in the deflate case we need to do a crc on the input
+ */
+ if (crc) {
+ ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
+ }
+
+ b = apr_bucket_heap_create((char *)ctx->buffer, len, NULL,
+ bb->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, b);
+
+ ctx->stream.next_out = ctx->buffer;
+ ctx->stream.avail_out = c->bufferSize;
+}
+
static int flush_libz_buffer(deflate_ctx *ctx, deflate_filter_config *c,
- struct apr_bucket_alloc_t *bucket_alloc,
int (*libz_func)(z_streamp, int), int flush,
int crc)
{
int zRC = Z_OK;
int done = 0;
- unsigned int deflate_len;
- apr_bucket *b;
+ int deflate_len;
for (;;) {
deflate_len = c->bufferSize - ctx->stream.avail_out;
-
- if (deflate_len != 0) {
- /*
- * Do we need to update ctx->crc? Usually this is the case for
- * inflate action where we need to do a crc on the output, whereas
- * in the deflate case we need to do a crc on the input
- */
- if (crc) {
- ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer,
- deflate_len);
- }
- b = apr_bucket_heap_create((char *)ctx->buffer,
- deflate_len, NULL,
- bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
- ctx->stream.next_out = ctx->buffer;
- ctx->stream.avail_out = c->bufferSize;
+ if (deflate_len > 0) {
+ consume_buffer(ctx, c, deflate_len, crc, ctx->bb);
}
if (done)
request_rec *r = f->r;
deflate_ctx *ctx = f->ctx;
int zRC;
+ apr_status_t rv;
apr_size_t len = 0, blen;
const char *data;
deflate_filter_config *c;
ctx->stream.avail_in = 0; /* should be zero already anyway */
/* flush the remaining data from the zlib buffers */
- flush_libz_buffer(ctx, c, f->c->bucket_alloc, deflate, Z_FINISH,
- NO_UPDATE_CRC);
+ flush_libz_buffer(ctx, c, deflate, Z_FINISH, NO_UPDATE_CRC);
buf = apr_palloc(r->pool, VALIDATION_SIZE);
putLong((unsigned char *)&buf[0], ctx->crc);
}
deflateEnd(&ctx->stream);
+
+ /* We've ended the libz stream, so remove ourselves. */
+ ap_remove_output_filter(f);
+
/* No need for cleanup any longer */
apr_pool_cleanup_kill(r->pool, ctx, deflate_ctx_cleanup);
/* Okay, we've seen the EOS.
* Time to pass it along down the chain.
*/
- return ap_pass_brigade(f->next, ctx->bb);
+ rv = ap_pass_brigade(f->next, ctx->bb);
+ apr_brigade_cleanup(ctx->bb);
+ return rv;
}
if (APR_BUCKET_IS_FLUSH(e)) {
- apr_status_t rv;
-
/* flush the remaining data from the zlib buffers */
- zRC = flush_libz_buffer(ctx, c, f->c->bucket_alloc, deflate,
- Z_SYNC_FLUSH, NO_UPDATE_CRC);
+ zRC = flush_libz_buffer(ctx, c, deflate, Z_SYNC_FLUSH,
+ NO_UPDATE_CRC);
if (zRC != Z_OK) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01385)
"Zlib error %d flushing zlib output buffer (%s)",
APR_BUCKET_REMOVE(e);
APR_BRIGADE_INSERT_TAIL(ctx->bb, e);
rv = ap_pass_brigade(f->next, ctx->bb);
+ apr_brigade_cleanup(ctx->bb);
if (rv != APR_SUCCESS) {
return rv;
}
}
/* read */
- apr_bucket_read(e, &data, &len, APR_BLOCK_READ);
+ rv = apr_bucket_read(e, &data, &len, APR_BLOCK_READ);
+ if (rv) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(10298)
+ "failed reading from %s bucket", e->type->name);
+ return rv;
+ }
if (!len) {
apr_bucket_delete(e);
continue;
ctx->stream.next_in = (unsigned char *)data; /* We just lost const-ness,
* but we'll just have to
* trust zlib */
- ctx->stream.avail_in = len;
+ ctx->stream.avail_in = (int)len;
while (ctx->stream.avail_in != 0) {
if (ctx->stream.avail_out == 0) {
- apr_status_t rv;
+ consume_buffer(ctx, c, c->bufferSize, NO_UPDATE_CRC, ctx->bb);
- ctx->stream.next_out = ctx->buffer;
- len = c->bufferSize - ctx->stream.avail_out;
-
- b = apr_bucket_heap_create((char *)ctx->buffer, len,
- NULL, f->c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
- ctx->stream.avail_out = c->bufferSize;
/* Send what we have right now to the next filter. */
rv = ap_pass_brigade(f->next, ctx->bb);
+ apr_brigade_cleanup(ctx->bb);
if (rv != APR_SUCCESS) {
return rv;
}
if (APR_BUCKET_IS_FLUSH(bkt)) {
apr_bucket *tmp_b;
- ctx->inflate_total += ctx->stream.avail_out;
- zRC = inflate(&(ctx->stream), Z_SYNC_FLUSH);
- ctx->inflate_total -= ctx->stream.avail_out;
- if (zRC != Z_OK) {
- inflateEnd(&ctx->stream);
- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01391)
- "Zlib error %d inflating data (%s)", zRC,
- ctx->stream.msg);
- return APR_EGENERAL;
- }
+ if (!ctx->done) {
+ ctx->inflate_total += ctx->stream.avail_out;
+ zRC = inflate(&(ctx->stream), Z_SYNC_FLUSH);
+ ctx->inflate_total -= ctx->stream.avail_out;
+ if (zRC != Z_OK) {
+ inflateEnd(&ctx->stream);
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01391)
+ "Zlib error %d inflating data (%s)", zRC,
+ ctx->stream.msg);
+ return APR_EGENERAL;
+ }
- if (inflate_limit && ctx->inflate_total > inflate_limit) {
- inflateEnd(&ctx->stream);
- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02647)
- "Inflated content length of %" APR_OFF_T_FMT
- " is larger than the configured limit"
- " of %" APR_OFF_T_FMT,
- ctx->inflate_total, inflate_limit);
- return APR_ENOSPC;
- }
-
- if (!check_ratio(r, ctx, dc)) {
- inflateEnd(&ctx->stream);
- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02805)
- "Inflated content ratio is larger than the "
- "configured limit %i by %i time(s)",
- dc->ratio_limit, dc->ratio_burst);
- return APR_EINVAL;
- }
+ if (inflate_limit && ctx->inflate_total > inflate_limit) {
+ inflateEnd(&ctx->stream);
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02647)
+ "Inflated content length of %" APR_OFF_T_FMT
+ " is larger than the configured limit"
+ " of %" APR_OFF_T_FMT,
+ ctx->inflate_total, inflate_limit);
+ return APR_ENOSPC;
+ }
- len = c->bufferSize - ctx->stream.avail_out;
- ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
- tmp_b = apr_bucket_heap_create((char *)ctx->buffer, len,
- NULL, f->c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(ctx->proc_bb, tmp_b);
+ if (!check_ratio(r, ctx, dc)) {
+ inflateEnd(&ctx->stream);
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02805)
+ "Inflated content ratio is larger than the "
+ "configured limit %i by %i time(s)",
+ dc->ratio_limit, dc->ratio_burst);
+ return APR_EINVAL;
+ }
- ctx->stream.next_out = ctx->buffer;
- ctx->stream.avail_out = c->bufferSize;
+ consume_buffer(ctx, c, c->bufferSize - ctx->stream.avail_out,
+ UPDATE_CRC, ctx->proc_bb);
+ }
/* Flush everything so far in the returning brigade, but continue
* reading should EOS/more follow (don't lose them).
if (!ctx->validation_buffer) {
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;
-
- 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;
+ consume_buffer(ctx, c, c->bufferSize, UPDATE_CRC,
+ ctx->proc_bb);
}
ctx->inflate_total += ctx->stream.avail_out;
}
if (ctx->validation_buffer) {
- apr_bucket *tmp_heap;
apr_size_t avail, valid;
unsigned char *buf = ctx->validation_buffer;
(apr_uint64_t)ctx->stream.total_in,
(apr_uint64_t)ctx->stream.total_out, r->uri);
- len = c->bufferSize - ctx->stream.avail_out;
-
- 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;
+ consume_buffer(ctx, c, c->bufferSize - ctx->stream.avail_out,
+ UPDATE_CRC, ctx->proc_bb);
{
unsigned long compCRC, compLen;
if (block == APR_BLOCK_READ &&
APR_BRIGADE_EMPTY(ctx->proc_bb) &&
ctx->stream.avail_out < c->bufferSize) {
- apr_bucket *tmp_heap;
- apr_size_t len;
- ctx->stream.next_out = ctx->buffer;
- len = c->bufferSize - ctx->stream.avail_out;
-
- 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;
+ consume_buffer(ctx, c, c->bufferSize - ctx->stream.avail_out,
+ UPDATE_CRC, ctx->proc_bb);
}
if (!APR_BRIGADE_EMPTY(ctx->proc_bb)) {
while (!APR_BRIGADE_EMPTY(bb))
{
const char *data;
- apr_bucket *b;
apr_size_t len;
e = APR_BRIGADE_FIRST(bb);
* fails, whereas in the deflate case you can empty a filled output
* buffer and call it again until no more output can be created.
*/
- flush_libz_buffer(ctx, c, f->c->bucket_alloc, inflate, Z_SYNC_FLUSH,
- UPDATE_CRC);
+ flush_libz_buffer(ctx, c, inflate, Z_SYNC_FLUSH, UPDATE_CRC);
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01398)
"Zlib: Inflated %" APR_UINT64_T_FMT
" to %" APR_UINT64_T_FMT " : URL %s",
* Okay, we've seen the EOS.
* Time to pass it along down the chain.
*/
- return ap_pass_brigade(f->next, ctx->bb);
+ rv = ap_pass_brigade(f->next, ctx->bb);
+ apr_brigade_cleanup(ctx->bb);
+ return rv;
}
if (APR_BUCKET_IS_FLUSH(e)) {
- apr_status_t rv;
-
/* flush the remaining data from the zlib buffers */
- zRC = flush_libz_buffer(ctx, c, f->c->bucket_alloc, inflate,
- Z_SYNC_FLUSH, UPDATE_CRC);
+ zRC = flush_libz_buffer(ctx, c, inflate, Z_SYNC_FLUSH, UPDATE_CRC);
if (zRC == Z_STREAM_END) {
if (ctx->validation_buffer == NULL) {
ctx->validation_buffer = apr_pcalloc(f->r->pool,
APR_BUCKET_REMOVE(e);
APR_BRIGADE_INSERT_TAIL(ctx->bb, e);
rv = ap_pass_brigade(f->next, ctx->bb);
+ apr_brigade_cleanup(ctx->bb);
if (rv != APR_SUCCESS) {
return rv;
}
while (ctx->stream.avail_in != 0) {
if (ctx->stream.avail_out == 0) {
- ctx->stream.next_out = ctx->buffer;
- len = c->bufferSize - ctx->stream.avail_out;
-
- ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
- b = apr_bucket_heap_create((char *)ctx->buffer, len,
- NULL, f->c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
- ctx->stream.avail_out = c->bufferSize;
+ consume_buffer(ctx, c, c->bufferSize, UPDATE_CRC, ctx->bb);
+
/* Send what we have right now to the next filter. */
rv = ap_pass_brigade(f->next, ctx->bb);
+ apr_brigade_cleanup(ctx->bb);
if (rv != APR_SUCCESS) {
return rv;
}
return APR_EGENERAL;
}
+ /* Don't check length limits on inflate_out */
if (!check_ratio(r, ctx, dc)) {
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02650)
"Inflated content ratio is larger than the "