Author: rhuijben
Date: Wed Nov 11 21:07:58 2015
New Revision: 1713932
URL: http://svn.apache.org/viewvc?rev=1713932&view=rev
Log:
Make the deflate buckets properly read to completion in all scenarios.
Fixing this made visible that the compress code calculated the crc and
size in the wrong way.
* buckets/deflate_buckets.c
(serf_deflate_destroy_and_data): Assume streams attached the other way
around.
(serf_deflate_refill): Always calculate the crc on the uncompressed data.
Store bytes in magic value as big endian.
(serf_deflate_wait_for_data): Attach input stream to the stream we read from
when done, to handle read to end promises.
(serf_deflate_read): Simplify by checking against DONE.
(serf_deflate_set_config): Avoid segfault when we are done reading from
stream.
Modified:
serf/trunk/buckets/deflate_buckets.c
Modified: serf/trunk/buckets/deflate_buckets.c
URL:
http://svn.apache.org/viewvc/serf/trunk/buckets/deflate_buckets.c?rev=1713932&r1=1713931&r2=1713932&view=diff
==============================================================================
--- serf/trunk/buckets/deflate_buckets.c (original)
+++ serf/trunk/buckets/deflate_buckets.c Wed Nov 11 21:07:58 2015
@@ -178,17 +178,22 @@ static void serf_deflate_destroy_and_dat
{
deflate_context_t *ctx = bucket->data;
- if (ctx->state > STATE_INIT &&
- ctx->state <= STATE_FINISH)
- inflateEnd(&ctx->zstream);
+ if ((ctx->state > STATE_INIT && ctx->state <= STATE_FINISH)
+ || (ctx->state > STATE_COMPRESS_INIT
+ && ctx->state < STATE_COMPRESS_FINISH))
+ {
+ if (ctx->memLevel >= 0)
+ deflateEnd(&ctx->zstream);
+ else
+ inflateEnd(&ctx->zstream);
+ }
- /* We may have appended inflate_stream into the stream bucket.
+ /* We may have appended stream into the inflate bucket.
* If so, avoid free'ing it twice.
*/
- if (ctx->inflate_stream) {
- serf_bucket_destroy(ctx->inflate_stream);
- }
- serf_bucket_destroy(ctx->stream);
+ serf_bucket_destroy(ctx->inflate_stream);
+ if (ctx->stream)
+ serf_bucket_destroy(ctx->stream);
serf_default_destroy_and_data(bucket);
}
@@ -237,6 +242,9 @@ static apr_status_t serf_deflate_refill(
if (private_len) {
ctx->zstream.next_in = (unsigned char*)private_data;
ctx->zstream.avail_in = private_len;
+ if (ctx->memLevel >= 0)
+ ctx->crc = crc32(ctx->crc, (const Bytef *)private_data,
+ private_len);
} else {
ctx->zstream.next_in = Z_NULL;
ctx->zstream.avail_in = 0;
@@ -259,8 +267,9 @@ static apr_status_t serf_deflate_refill(
ctx->zstream.next_out = ctx->buffer;
private_len = ctx->bufferSize - ctx->zstream.avail_out;
- ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer,
- private_len);
+ if (ctx->memLevel < 0)
+ ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer,
+ private_len);
/* FIXME: There probably needs to be a free func. */
tmp = SERF_BUCKET_SIMPLE_STRING_LEN((char *)ctx->buffer,
@@ -278,8 +287,9 @@ static apr_status_t serf_deflate_refill(
serf_bucket_t *tmp;
private_len = ctx->bufferSize - ctx->zstream.avail_out;
- ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer,
- private_len);
+ if (ctx->memLevel < 0)
+ ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer,
+ private_len);
/* FIXME: There probably needs to be a free func. */
tmp = SERF_BUCKET_SIMPLE_STRING_LEN((char *)ctx->buffer,
private_len,
@@ -313,15 +323,15 @@ static apr_status_t serf_deflate_refill(
bucket->allocator,
DEFLATE_VERIFY_SIZE);
- verify_header[0] = (ctx->crc >> 24) & 0xFF;
- verify_header[1] = (ctx->crc >> 16) & 0xFF;
- verify_header[2] = (ctx->crc >> 8) & 0xFF;
- verify_header[3] = ctx->crc & 0xFF;
-
- verify_header[4] = (ctx->zstream.total_out >> 24) & 0xFF;
- verify_header[5] = (ctx->zstream.total_out >> 16) & 0xFF;
- verify_header[6] = (ctx->zstream.total_out >> 8) & 0xFF;
- verify_header[7] = ctx->zstream.total_out & 0xFF;
+ verify_header[0] = ctx->crc & 0xFF;
+ verify_header[1] = (ctx->crc >> 8) & 0xFF;
+ verify_header[2] = (ctx->crc >> 16) & 0xFF;
+ verify_header[3] = (ctx->crc >> 24) & 0xFF;
+
+ verify_header[4] = ctx->zstream.total_in & 0xFF;
+ verify_header[5] = (ctx->zstream.total_in >> 8) & 0xFF;
+ verify_header[6] = (ctx->zstream.total_in >> 16) & 0xFF;
+ verify_header[7] = (ctx->zstream.total_in >> 24) & 0xFF;
serf_bucket_aggregate_append(
ctx->inflate_stream,
@@ -465,9 +475,10 @@ static apr_status_t serf_deflate_wait_fo
break;
case STATE_FINISH:
inflateEnd(&ctx->zstream);
- serf_bucket_aggregate_prepend(ctx->stream, ctx->inflate_stream);
- ctx->inflate_stream = 0;
- ctx->state++;
+ serf_bucket_aggregate_append(ctx->inflate_stream,
+ ctx->stream);
+ ctx->stream = NULL;
+ ctx->state = STATE_DONE;
break;
case STATE_INFLATE:
return APR_SUCCESS;
@@ -506,9 +517,10 @@ static apr_status_t serf_deflate_wait_fo
break;
case STATE_COMPRESS_FINISH:
deflateEnd(&ctx->zstream);
- serf_bucket_aggregate_prepend(ctx->stream, ctx->inflate_stream);
- ctx->inflate_stream = NULL;
- ctx->state++;
+ serf_bucket_aggregate_append(ctx->inflate_stream,
+ ctx->stream);
+ ctx->stream = NULL;
+ ctx->state = STATE_DONE;
break;
default:
/* Not reachable */
@@ -534,7 +546,7 @@ static apr_status_t serf_deflate_read(se
}
status = serf_bucket_read(ctx->inflate_stream, requested, data, len);
- if (APR_STATUS_IS_EOF(status))
+ if (APR_STATUS_IS_EOF(status) && ctx->state != STATE_DONE)
status = APR_SUCCESS;
if (status || *len || ctx->state != STATE_INFLATE) {
@@ -555,7 +567,7 @@ static apr_status_t serf_deflate_read(se
if (APR_STATUS_IS_EOF(status)) {
/* If the inflation wasn't finished, return APR_SUCCESS. */
- if (ctx->state == STATE_INFLATE)
+ if (ctx->state != STATE_DONE)
return APR_SUCCESS; /* Not at EOF yet */
/* If our stream is finished too and all data was inflated,
@@ -567,7 +579,7 @@ static apr_status_t serf_deflate_read(se
should have been advanced to STATE_READING_VERIFY or
STATE_FINISH. If not, then the data was incomplete
and we have an error. */
- if (ctx->state != STATE_INFLATE)
+ if (ctx->state != STATE_DONE)
return APR_SUCCESS;
else {
serf__log(LOGLVL_ERROR, LOGCOMP_COMPR, __FILE__,
@@ -650,7 +662,10 @@ static apr_status_t serf_deflate_set_con
ctx->config = config;
- return serf_bucket_set_config(ctx->stream, config);
+ if (ctx->stream)
+ return serf_bucket_set_config(ctx->stream, config);
+
+ return APR_SUCCESS;
}
const serf_bucket_type_t serf_bucket_type_deflate = {