serf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kot...@apache.org
Subject svn commit: r1805301 - in /serf/trunk: buckets/deflate_buckets.c test/test_buckets.c
Date Thu, 17 Aug 2017 15:29:06 GMT
Author: kotkov
Date: Thu Aug 17 15:29:06 2017
New Revision: 1805301

URL: http://svn.apache.org/viewvc?rev=1805301&view=rev
Log:
Fix an endless loop in the deflate bucket with the truncated input.

The endless loop can be triggered by how this bucket has been handling
Z_BUF_ERROR, which is returned when zlib can't move forward, either when
it requires more output space (1), or there is no more input (2).

We have been handling such errors by resetting the output buffer and
continuing, but this only handles (1).  In case of the truncated input,
we are dealing with (2), and resetting the output buffer doesn't help —
and that has been causing the endless loop.  Fix this by separately
handling the case with Z_BUF_ERROR and no more input.

* buckets/deflate_buckets.c
  (serf_deflate_refill): Handle a case when we hit the end of input
   stream and zlib can't continue, even though there's enough output
   space.  If that happens, return an error.

* test/test_buckets.c
  (test_deflate_bucket_truncated_data): New test, fails without the fix.
  (test_buckets): Add new test.

Modified:
    serf/trunk/buckets/deflate_buckets.c
    serf/trunk/test/test_buckets.c

Modified: serf/trunk/buckets/deflate_buckets.c
URL: http://svn.apache.org/viewvc/serf/trunk/buckets/deflate_buckets.c?rev=1805301&r1=1805300&r2=1805301&view=diff
==============================================================================
--- serf/trunk/buckets/deflate_buckets.c (original)
+++ serf/trunk/buckets/deflate_buckets.c Thu Aug 17 15:29:06 2017
@@ -277,14 +277,24 @@ static apr_status_t serf_deflate_refill(
 
     while (1) {
 
-        if (ctx->memLevel < 0)
+        if (ctx->memLevel < 0) {
             zRC = inflate(&ctx->zstream, flush_v);
-        else
+            if (zRC == Z_BUF_ERROR && APR_STATUS_IS_EOF(ctx->stream_status) &&
+                ctx->zstream.avail_out > 0) {
+                /* Zlib can't continue, although there's still space in the
+                   output buffer.  This can happen either if the stream is
+                   truncated or corrupted.  As we don't know for sure,
+                   return a generic error. */
+                return SERF_ERROR_DECOMPRESSION_FAILED;
+            }
+        }
+        else {
             zRC = deflate(&ctx->zstream, flush_v);
+        }
 
-        /* We're full or zlib requires more space. Either case, clear
-            out our buffer, reset, and return. */
         if (zRC == Z_BUF_ERROR || ctx->zstream.avail_out == 0) {
+            /* We're full or zlib requires more space. Either case, clear
+               out our buffer, reset, and return. */
             apr_size_t private_len;
             serf_bucket_t *tmp;
 

Modified: serf/trunk/test/test_buckets.c
URL: http://svn.apache.org/viewvc/serf/trunk/test/test_buckets.c?rev=1805301&r1=1805300&r2=1805301&view=diff
==============================================================================
--- serf/trunk/test/test_buckets.c (original)
+++ serf/trunk/test/test_buckets.c Thu Aug 17 15:29:06 2017
@@ -3267,6 +3267,33 @@ static void test_brotli_decompress_respo
     serf_bucket_destroy(bkt);
 }
 
+static void test_deflate_bucket_truncated_data(CuTest *tc)
+{
+    test_baton_t *tb = tc->testBaton;
+    serf_bucket_t *input;
+    serf_bucket_t *bkt;
+    serf_bucket_alloc_t *alloc = test__create_bucket_allocator(tc, tb->pool);
+
+    /* This is a valid, but truncated gzip data (in two chunks). */
+    input = serf_bucket_aggregate_create(alloc);
+    serf_bucket_aggregate_append(input,
+        SERF_BUCKET_SIMPLE_STRING_LEN("\x1F\x8B\x08\x00\x00", 5, alloc));
+    serf_bucket_aggregate_append(input,
+        SERF_BUCKET_SIMPLE_STRING_LEN("\x00\x00\x00\x00\x03", 5, alloc));
+
+    bkt = serf_bucket_deflate_create(input, alloc, SERF_DEFLATE_GZIP);
+    {
+        char buf[1024];
+        apr_size_t len;
+        apr_status_t status;
+
+        status = read_all(bkt, buf, sizeof(buf), &len);
+        CuAssertIntEquals(tc, SERF_ERROR_DECOMPRESSION_FAILED, status);
+    }
+
+    serf_bucket_destroy(bkt);
+}
+
 CuSuite *test_buckets(void)
 {
     CuSuite *suite = CuSuiteNew();
@@ -3326,6 +3353,7 @@ CuSuite *test_buckets(void)
        data so it's disabled by default. */
     SUITE_ADD_TEST(suite, test_deflate_4GBplus_buckets);
 #endif
+    SUITE_ADD_TEST(suite, test_deflate_bucket_truncated_data);
 
 
 



Mime
View raw message