[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#771758: unblock (pre-approval): serf/1.3.8-1



Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock

Please unblock package serf

The upstream 1.3.8 release is a minor bug fix release.  One of the three
functional changes is to disable use of SSLv2/SSLv3.  I'd like to
include all the changes, but the SSL changes seem most relevant, so if
needed I can instead backport just that patch.

Attached are the full debdiff and a debdiff excluding the changes to the
test directory.

unblock serf/1.3.8-1

-- System Information:
Debian Release: 8.0
  APT prefers unstable
  APT policy: (500, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 3.16.0-4-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

-- 
James
GPG Key: 4096R/331BA3DB 2011-12-05 James McCoy <jamessan@debian.org>
diffstat for serf-1.3.7 serf-1.3.8

 CHANGES                                |    8 
 auth/auth_spnego_sspi.c                |    4 
 buckets/deflate_buckets.c              |   37 ++-
 buckets/ssl_buckets.c                  |    2 
 debian/changelog                       |   10 
 debian/patches/comment-style_r2443     |   19 +
 debian/patches/series                  |    2 
 debian/patches/test-memory-usage_r2445 |   61 +++++
 serf.h                                 |    2 
 test/test_buckets.c                    |  350 +++++++++++++++++++++++++++++++++
 test/test_serf.h                       |    3 
 11 files changed, 485 insertions(+), 13 deletions(-)

diff -Nru serf-1.3.7/auth/auth_spnego_sspi.c serf-1.3.8/auth/auth_spnego_sspi.c
--- serf-1.3.7/auth/auth_spnego_sspi.c	2014-02-04 14:41:14.000000000 -0500
+++ serf-1.3.8/auth/auth_spnego_sspi.c	2014-10-19 14:38:11.000000000 -0400
@@ -95,8 +95,8 @@
     }
 
     if (SecIsValidHandle(&ctx->sspi_credentials)) {
-        FreeCredentialsHandle(&ctx->sspi_context);
-        SecInvalidateHandle(&ctx->sspi_context);
+        FreeCredentialsHandle(&ctx->sspi_credentials);
+        SecInvalidateHandle(&ctx->sspi_credentials);
     }
 
     return APR_SUCCESS;
diff -Nru serf-1.3.7/buckets/deflate_buckets.c serf-1.3.8/buckets/deflate_buckets.c
--- serf-1.3.7/buckets/deflate_buckets.c	2011-06-23 22:03:57.000000000 -0400
+++ serf-1.3.8/buckets/deflate_buckets.c	2014-10-19 14:38:11.000000000 -0400
@@ -141,7 +141,6 @@
                                       const char **data, apr_size_t *len)
 {
     deflate_context_t *ctx = bucket->data;
-    unsigned long compCRC, compLen;
     apr_status_t status;
     const char *private_data;
     apr_size_t private_len;
@@ -186,17 +185,25 @@
             ctx->state++;
             break;
         case STATE_VERIFY:
+        {
+            unsigned long compCRC, compLen, actualLen;
+
             /* Do the checksum computation. */
             compCRC = getLong((unsigned char*)ctx->hdr_buffer);
             if (ctx->crc != compCRC) {
                 return SERF_ERROR_DECOMPRESSION_FAILED;
             }
             compLen = getLong((unsigned char*)ctx->hdr_buffer + 4);
-            if (ctx->zstream.total_out != compLen) {
+            /* The length in the trailer is module 2^32, so do the same for
+               the actual length. */
+            actualLen = ctx->zstream.total_out;
+            actualLen &= 0xFFFFFFFF;
+            if (actualLen != compLen) {
                 return SERF_ERROR_DECOMPRESSION_FAILED;
             }
             ctx->state++;
             break;
+        }
         case STATE_INIT:
             zRC = inflateInit2(&ctx->zstream, ctx->windowSize);
             if (zRC != Z_OK) {
@@ -264,10 +271,14 @@
                 ctx->zstream.next_in = (unsigned char*)private_data;
                 ctx->zstream.avail_in = private_len;
             }
-            zRC = Z_OK;
-            while (ctx->zstream.avail_in != 0) {
-                /* We're full, clear out our buffer, reset, and return. */
-                if (ctx->zstream.avail_out == 0) {
+
+            while (1) {
+
+                zRC = inflate(&ctx->zstream, Z_NO_FLUSH);
+
+                /* 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) {
                     serf_bucket_t *tmp;
                     ctx->zstream.next_out = ctx->buffer;
                     private_len = ctx->bufferSize - ctx->zstream.avail_out;
@@ -283,7 +294,6 @@
                     ctx->zstream.avail_out = ctx->bufferSize;
                     break;
                 }
-                zRC = inflate(&ctx->zstream, Z_NO_FLUSH);
 
                 if (zRC == Z_STREAM_END) {
                     serf_bucket_t *tmp;
@@ -330,9 +340,13 @@
 
                     break;
                 }
+
+                /* Any other error? */
                 if (zRC != Z_OK) {
                     return SERF_ERROR_DECOMPRESSION_FAILED;
                 }
+
+                /* As long as zRC == Z_OK, just keep looping. */
             }
             /* Okay, we've inflated.  Try to read. */
             status = serf_bucket_read(ctx->inflate_stream, requested, data,
@@ -340,8 +354,13 @@
             /* Hide EOF. */
             if (APR_STATUS_IS_EOF(status)) {
                 status = ctx->stream_status;
-                /* If our stream is finished too, return SUCCESS so
-                 * we'll iterate one more time.
+
+                /* If the inflation wasn't finished, return APR_SUCCESS. */
+                if (zRC != Z_STREAM_END)
+                    return APR_SUCCESS;
+
+                /* If our stream is finished too and all data was inflated,
+                 * return SUCCESS so we'll iterate one more time.
                  */
                 if (APR_STATUS_IS_EOF(status)) {
                     /* No more data to read from the stream, and everything
diff -Nru serf-1.3.7/buckets/ssl_buckets.c serf-1.3.8/buckets/ssl_buckets.c
--- serf-1.3.7/buckets/ssl_buckets.c	2014-08-05 22:24:00.000000000 -0400
+++ serf-1.3.8/buckets/ssl_buckets.c	2014-10-19 14:38:11.000000000 -0400
@@ -1317,7 +1317,9 @@
     ssl_ctx->pool = serf_bucket_allocator_get_pool(allocator);
     ssl_ctx->allocator = allocator;
 
+    /* Use the best possible protocol version, but disable the broken SSLv2/3 */
     ssl_ctx->ctx = SSL_CTX_new(SSLv23_client_method());
+    SSL_CTX_set_options(ssl_ctx->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
 
     SSL_CTX_set_client_cert_cb(ssl_ctx->ctx, ssl_need_client_cert);
     ssl_ctx->cached_cert = 0;
diff -Nru serf-1.3.7/CHANGES serf-1.3.8/CHANGES
--- serf-1.3.7/CHANGES	2014-08-11 11:17:02.000000000 -0400
+++ serf-1.3.8/CHANGES	2014-10-20 15:08:16.000000000 -0400
@@ -1,10 +1,18 @@
+Serf 1.3.8 [2014-10-20, from /tags/1.3.8, rxxxx]
+Fix issue #152: CRC calculation error for gzipped http reponses > 4GB.
+Fix issue #153: SSPI CredHandle not freed when APR pool is destroyed.
+Fix issue #154: Disable SSLv2 and SSLv3 as both or broken.
+
+
 Serf 1.3.7 [2014-08-11, from /tags/1.3.7, r2411]
   Handle NUL bytes in fields of an X.509 certificate. (r2393, r2399)
 
+
 Serf 1.3.6 [2014-06-09, from /tags/1.3.6, r2372]
   Revert r2319 from serf 1.3.5: this change was making serf call handle_response
     multiple times in case of an error response, leading to unexpected behavior.
 
+
 Serf 1.3.5 [2014-04-27, from /tags/1.3.5, r2355]
   Fix issue #125: no reverse lookup during Negotiate authentication for proxies.
   Fix a crash caused by incorrect reuse of the ssltunnel CONNECT request (r2316)
diff -Nru serf-1.3.7/debian/changelog serf-1.3.8/debian/changelog
--- serf-1.3.7/debian/changelog	2014-12-01 22:35:31.000000000 -0500
+++ serf-1.3.8/debian/changelog	2014-12-01 22:35:31.000000000 -0500
@@ -1,3 +1,13 @@
+serf (1.3.8-1) UNRELEASED; urgency=medium
+
+  * New upstream release
+    - Disable SSLv2 and SSLv3
+  * Backport r2445 from upstream to fix potential memory allocation failures
+    in the test suite.
+  * Backport r2443 from upstream to fix a compile failure in the test suite.
+
+ -- James McCoy <jamessan@debian.org>  Mon, 01 Dec 2014 22:11:04 -0500
+
 serf (1.3.7-3) unstable; urgency=medium
 
   * Specify the proper prefix/libdir when building libserf-1.pc.
diff -Nru serf-1.3.7/debian/patches/comment-style_r2443 serf-1.3.8/debian/patches/comment-style_r2443
--- serf-1.3.7/debian/patches/comment-style_r2443	1969-12-31 19:00:00.000000000 -0500
+++ serf-1.3.8/debian/patches/comment-style_r2443	2014-12-01 22:35:31.000000000 -0500
@@ -0,0 +1,19 @@
+Subject: Correct comment style
+Description:
+ * test/test_buckets.c
+   (deflate_compress): Correct comment style not supported by strict
+   compilers
+Origin: upstream, r2443
+--- a/test/test_buckets.c
++++ b/test/test_buckets.c
+@@ -1232,9 +1232,9 @@
+ 
+     /* The largest buffer we should need is 0.1% larger than the
+        uncompressed data, + 12 bytes. This info comes from zlib.h.
++       buf_size = orig_len + (orig_len / 1000) + 12;
+        Note: This isn't sufficient when using Z_NO_FLUSH and extremely compressed
+        data. Use a buffer bigger than what we need. */
+-//    buf_size = orig_len + (orig_len / 1000) + 12;
+     buf_size = 100000;
+ 
+     write_buf = apr_palloc(pool, buf_size);
diff -Nru serf-1.3.7/debian/patches/series serf-1.3.8/debian/patches/series
--- serf-1.3.7/debian/patches/series	2014-12-01 22:35:31.000000000 -0500
+++ serf-1.3.8/debian/patches/series	2014-12-01 22:35:31.000000000 -0500
@@ -1 +1,3 @@
 libtool
+test-memory-usage_r2445
+comment-style_r2443
diff -Nru serf-1.3.7/debian/patches/test-memory-usage_r2445 serf-1.3.8/debian/patches/test-memory-usage_r2445
--- serf-1.3.7/debian/patches/test-memory-usage_r2445	1969-12-31 19:00:00.000000000 -0500
+++ serf-1.3.8/debian/patches/test-memory-usage_r2445	2014-12-01 22:35:31.000000000 -0500
@@ -0,0 +1,61 @@
+Subject: Reduce memory usage by deflate bucket test.
+Origin: upstream, r2445
+--- a/test/test_buckets.c
++++ b/test/test_buckets.c
+@@ -1309,12 +1309,12 @@
+                           expected_len);
+ }
+ 
+-static void deflate_buckets(CuTest *tc, int nr_of_loops)
++static void deflate_buckets(CuTest *tc, int nr_of_loops, apr_pool_t *pool)
+ {
+     const char *msg = "12345678901234567890123456789012345678901234567890";
+ 
+     test_baton_t *tb = tc->testBaton;
+-    serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(tb->pool, NULL,
++    serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(pool, NULL,
+                                                               NULL);
+     z_stream zdestr;
+     int i;
+@@ -1333,8 +1333,8 @@
+     {
+         serf_config_t *config;
+ 
+-        serf_context_t *ctx = serf_context_create(tb->pool);
+-        /* status = */ serf__config_store_get_config(ctx, NULL, &config, tb->pool);
++        serf_context_t *ctx = serf_context_create(pool);
++        /* status = */ serf__config_store_get_config(ctx, NULL, &config, pool);
+ 
+         serf_bucket_set_config(defbkt, config);
+     }
+@@ -1356,11 +1356,11 @@
+         if (i == nr_of_loops - 1) {
+             CuAssertIntEquals(tc, APR_SUCCESS,
+                               deflate_compress(&data, &len, &zdestr, msg,
+-                                               strlen(msg), 1, tb->pool));
++                                               strlen(msg), 1, pool));
+         } else {
+             CuAssertIntEquals(tc, APR_SUCCESS,
+                               deflate_compress(&data, &len, &zdestr, msg,
+-                                               strlen(msg), 0, tb->pool));
++                                               strlen(msg), 0, pool));
+         }
+ 
+         if (len == 0)
+@@ -1378,10 +1378,15 @@
+ static void test_deflate_buckets(CuTest *tc)
+ {
+     int i;
++    apr_pool_t *iterpool;
++    test_baton_t *tb = tc->testBaton;
+ 
++    apr_pool_create(&iterpool, tb->pool);
+     for (i = 1; i < 1000; i++) {
+-        deflate_buckets(tc, i);
++        apr_pool_clear(iterpool);
++        deflate_buckets(tc, i, iterpool);
+     }
++    apr_pool_destroy(iterpool);
+ }
+ 
+ static apr_status_t discard_data(serf_bucket_t *bkt,
diff -Nru serf-1.3.7/serf.h serf-1.3.8/serf.h
--- serf-1.3.7/serf.h	2014-08-04 14:11:28.000000000 -0400
+++ serf-1.3.8/serf.h	2014-10-19 14:20:09.000000000 -0400
@@ -1062,7 +1062,7 @@
 /* Version info */
 #define SERF_MAJOR_VERSION 1
 #define SERF_MINOR_VERSION 3
-#define SERF_PATCH_VERSION 7
+#define SERF_PATCH_VERSION 8
 
 /* Version number string */
 #define SERF_VERSION_STRING APR_STRINGIFY(SERF_MAJOR_VERSION) "." \
diff -Nru serf-1.3.7/test/test_buckets.c serf-1.3.8/test/test_buckets.c
--- serf-1.3.7/test/test_buckets.c	2013-09-29 02:37:46.000000000 -0400
+++ serf-1.3.8/test/test_buckets.c	2014-10-19 14:38:11.000000000 -0400
@@ -16,6 +16,8 @@
 #include <apr.h>
 #include <apr_pools.h>
 #include <apr_strings.h>
+#include <apr_random.h>
+#include <zlib.h>
 
 #include "serf.h"
 #include "test_serf.h"
@@ -1218,6 +1220,347 @@
     }
 }
 
+static apr_status_t deflate_compress(const char **data, apr_size_t *len,
+                                     z_stream *zdestr,
+                                     const char *orig, apr_size_t orig_len,
+                                     int last,
+                                     apr_pool_t *pool)
+{
+    int zerr;
+    apr_size_t buf_size;
+    void *write_buf;
+
+    /* The largest buffer we should need is 0.1% larger than the
+       uncompressed data, + 12 bytes. This info comes from zlib.h.
+       Note: This isn't sufficient when using Z_NO_FLUSH and extremely compressed
+       data. Use a buffer bigger than what we need. */
+//    buf_size = orig_len + (orig_len / 1000) + 12;
+    buf_size = 100000;
+
+    write_buf = apr_palloc(pool, buf_size);
+
+    zdestr->next_in = (Bytef *)orig;  /* Casting away const! */
+    zdestr->avail_in = (uInt)orig_len;
+
+    zerr = Z_OK;
+    zdestr->next_out = write_buf;
+    zdestr->avail_out = (uInt)buf_size;
+
+    while ((last && zerr != Z_STREAM_END) ||
+           (!last && zdestr->avail_in > 0))
+    {
+        zerr = deflate(zdestr, last ? Z_FINISH : Z_NO_FLUSH);
+        if (zerr < 0)
+            return APR_EGENERAL;
+    }
+
+    *data = write_buf;
+    *len = buf_size - zdestr->avail_out;
+    
+    return APR_SUCCESS;
+}
+
+/* Reads bucket until EOF found and compares read data with zero terminated
+ string expected. Report all failures using CuTest. */
+static void read_bucket_and_check_pattern(CuTest *tc, serf_bucket_t *bkt,
+                                          const char *pattern,
+                                          apr_size_t expected_len)
+{
+    apr_status_t status;
+    const char *expected;
+    const apr_size_t pattern_len = strlen(pattern);
+
+    apr_size_t exp_rem = 0;
+    apr_size_t actual_len = 0;
+
+    do
+    {
+        const char *data;
+        apr_size_t act_rem;
+
+        status = serf_bucket_read(bkt, SERF_READ_ALL_AVAIL, &data, &act_rem);
+
+        CuAssert(tc, "Got error during bucket reading.",
+                 !SERF_BUCKET_READ_ERROR(status));
+
+        actual_len += act_rem;
+
+        while (act_rem > 0) {
+            apr_size_t bytes_to_compare;
+
+            if (exp_rem == 0) {
+                expected = pattern;
+                exp_rem = pattern_len;
+            }
+
+            bytes_to_compare = act_rem < exp_rem ? act_rem : exp_rem;
+            CuAssert(tc, "Read data is not equal to expected.",
+                     strncmp(expected, data, bytes_to_compare) == 0);
+            data += bytes_to_compare;
+            act_rem -= bytes_to_compare;
+
+            expected += bytes_to_compare;
+            exp_rem -= bytes_to_compare;
+        }
+    } while(!APR_STATUS_IS_EOF(status));
+
+    CuAssertIntEquals_Msg(tc, "Read less data than expected.", 0, exp_rem);
+    CuAssertIntEquals_Msg(tc, "Read less/more data than expected.", actual_len,
+                          expected_len);
+}
+
+static void deflate_buckets(CuTest *tc, int nr_of_loops)
+{
+    const char *msg = "12345678901234567890123456789012345678901234567890";
+
+    test_baton_t *tb = tc->testBaton;
+    serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(tb->pool, NULL,
+                                                              NULL);
+    z_stream zdestr;
+    int i;
+    const char gzip_header[10] =
+    { '\037', '\213', Z_DEFLATED, 0,
+        0, 0, 0, 0, /* mtime */
+        0, 0x03 /* Unix OS_CODE */
+    };
+
+    serf_bucket_t *aggbkt = serf_bucket_aggregate_create(alloc);
+    serf_bucket_t *defbkt = serf_bucket_deflate_create(aggbkt, alloc,
+                                                       SERF_DEFLATE_GZIP);
+    serf_bucket_t *strbkt;
+
+#if 0 /* Enable logging */
+    {
+        serf_config_t *config;
+
+        serf_context_t *ctx = serf_context_create(tb->pool);
+        /* status = */ serf__config_store_get_config(ctx, NULL, &config, tb->pool);
+
+        serf_bucket_set_config(defbkt, config);
+    }
+#endif
+
+    memset(&zdestr, 0, sizeof(z_stream));
+    /* HTTP uses raw deflate format, so windows size => -15 */
+    CuAssert(tc, "zlib init failed.",
+             deflateInit2(&zdestr, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 8,
+                          Z_DEFAULT_STRATEGY) == Z_OK);
+
+    strbkt = SERF_BUCKET_SIMPLE_STRING_LEN(gzip_header, 10, alloc);
+    serf_bucket_aggregate_append(aggbkt, strbkt);
+
+    for (i = 0; i < nr_of_loops; i++) {
+        const char *data;
+        apr_size_t len;
+
+        if (i == nr_of_loops - 1) {
+            CuAssertIntEquals(tc, APR_SUCCESS,
+                              deflate_compress(&data, &len, &zdestr, msg,
+                                               strlen(msg), 1, tb->pool));
+        } else {
+            CuAssertIntEquals(tc, APR_SUCCESS,
+                              deflate_compress(&data, &len, &zdestr, msg,
+                                               strlen(msg), 0, tb->pool));
+        }
+
+        if (len == 0)
+            continue;
+
+        strbkt = SERF_BUCKET_SIMPLE_STRING_LEN(data, len, alloc);
+
+        serf_bucket_aggregate_append(aggbkt, strbkt);
+    }
+
+    tb->user_baton_l = APR_EOF;
+    read_bucket_and_check_pattern(tc, defbkt, msg, nr_of_loops * strlen(msg));
+}
+
+static void test_deflate_buckets(CuTest *tc)
+{
+    int i;
+
+    for (i = 1; i < 1000; i++) {
+        deflate_buckets(tc, i);
+    }
+}
+
+static apr_status_t discard_data(serf_bucket_t *bkt,
+                                 apr_size_t *read_len)
+{
+    const char *data;
+    apr_size_t data_len;
+    apr_status_t status;
+    apr_size_t read;
+
+    read = 0;
+
+    do
+    {
+        status = serf_bucket_read(bkt, SERF_READ_ALL_AVAIL, &data, &data_len);
+
+        if (!SERF_BUCKET_READ_ERROR(status)) {
+            read += data_len;
+        }
+    } while(status == APR_SUCCESS);
+
+    *read_len = read;
+    return status;
+}
+
+static apr_status_t hold_open(void *baton, serf_bucket_t *aggbkt)
+{
+    test_baton_t *tb = baton;
+
+    return tb->user_baton_l;
+}
+
+static void put_32bit(unsigned char *buf, unsigned long x)
+{
+    buf[0] = (unsigned char)(x & 0xFF);
+    buf[1] = (unsigned char)((x & 0xFF00) >> 8);
+    buf[2] = (unsigned char)((x & 0xFF0000) >> 16);
+    buf[3] = (unsigned char)((x & 0xFF000000) >> 24);
+}
+
+static serf_bucket_t *
+create_gzip_deflate_bucket(serf_bucket_t *stream, z_stream *outzstr,
+                           serf_bucket_alloc_t *alloc)
+{
+    serf_bucket_t *strbkt;
+    serf_bucket_t *defbkt = serf_bucket_deflate_create(stream, alloc,
+                                                       SERF_DEFLATE_GZIP);
+    int zerr;
+
+    memset(outzstr, 0, sizeof(z_stream));
+
+    const char gzip_header[10] =
+    { '\037', '\213', Z_DEFLATED, 0,
+        0, 0, 0, 0, /* mtime */
+        0, 0x03 /* Unix OS_CODE */
+    };
+
+    /* HTTP uses raw deflate format, so windows size => -15 */
+    zerr = deflateInit2(outzstr, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 8,
+                            Z_DEFAULT_STRATEGY);
+    if (zerr != Z_OK)
+        return NULL;
+
+    strbkt = SERF_BUCKET_SIMPLE_STRING_LEN(gzip_header, 10, alloc);
+    serf_bucket_aggregate_append(stream, strbkt);
+
+    return defbkt;
+}
+
+/* Test for issue #152: the trailers of gzipped data only store the 4 most 
+   significant bytes of the length, so when the compressed data is >4GB
+   we can't just compare actual length with expected length. */
+static void test_deflate_4GBplus_buckets(CuTest *tc)
+{
+    test_baton_t *tb = tc->testBaton;
+    serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(tb->pool, NULL,
+                                                              NULL);
+    int i;
+    unsigned char gzip_trailer[8];
+    z_stream zdestr;
+    serf_bucket_t *aggbkt = serf_bucket_aggregate_create(alloc);
+    serf_bucket_t *defbkt = create_gzip_deflate_bucket(aggbkt, &zdestr, alloc);
+    serf_bucket_t *strbkt;
+    apr_pool_t *iter_pool;
+    apr_size_t actual_size;
+    unsigned long unc_crc = 0;
+    unsigned long unc_length = 0;
+
+#define NR_OF_LOOPS 550000
+#define BUFSIZE 8096
+    unsigned char uncompressed[BUFSIZE];
+
+    serf_bucket_aggregate_hold_open(aggbkt, hold_open, tb);
+    tb->user_baton_l = APR_EAGAIN;
+
+
+#if 0 /* Enable logging */
+    {
+        serf_config_t *config;
+
+        serf_context_t *ctx = serf_context_create(tb->pool);
+        /* status = */ serf__config_store_get_config(ctx, NULL, &config, tb->pool);
+
+        serf_bucket_set_config(defbkt, config);
+    }
+#endif
+
+    apr_pool_create(&iter_pool, tb->pool);
+
+    actual_size = 0;
+    for (i = 0; i < NR_OF_LOOPS; i++) {
+        const char *data;
+        apr_size_t len;
+        apr_size_t read_len;
+        serf_bucket_alloc_t *iter_alloc;
+        apr_status_t status;
+
+        apr_pool_clear(iter_pool);
+        iter_alloc = serf_bucket_allocator_create(iter_pool, NULL, NULL);
+
+
+        if (i % 1000 == 0)
+            printf("%d\n", i);
+
+        status = apr_generate_random_bytes(uncompressed, BUFSIZE);
+        CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+        unc_crc = crc32(unc_crc, (const Bytef *)uncompressed, BUFSIZE);
+        unc_length += BUFSIZE;
+
+        if (i == NR_OF_LOOPS - 1) {
+            CuAssertIntEquals(tc, APR_SUCCESS,
+                              deflate_compress(&data, &len, &zdestr,
+                                               (const char *)uncompressed,
+                                               BUFSIZE, 1, iter_pool));
+        } else {
+            CuAssertIntEquals(tc, APR_SUCCESS,
+                              deflate_compress(&data, &len, &zdestr,
+                                               (const char *)uncompressed,
+                                               BUFSIZE, 0, iter_pool));
+        }
+
+        if (len == 0)
+            continue;
+
+        strbkt = serf_bucket_simple_copy_create(data, len, iter_alloc);
+        serf_bucket_aggregate_append(aggbkt, strbkt);
+
+        /* Start reading inflated data */
+        status = discard_data(defbkt, &read_len);
+        CuAssert(tc, "Got error during discarding of compressed data.",
+                 !SERF_BUCKET_READ_ERROR(status));
+
+        actual_size += read_len;
+    }
+
+    put_32bit(&gzip_trailer[0], unc_crc);
+    put_32bit(&gzip_trailer[4], unc_length);
+    strbkt = SERF_BUCKET_SIMPLE_STRING_LEN((const char *)gzip_trailer,
+                                           sizeof(gzip_trailer), alloc);
+    serf_bucket_aggregate_append(aggbkt, strbkt);
+
+    tb->user_baton_l = APR_EOF;
+
+    while (1) {
+        apr_size_t read_len;
+        apr_status_t status = discard_data(defbkt, &read_len);
+        CuAssert(tc, "Got error during discarding of compressed data.",
+                 !SERF_BUCKET_READ_ERROR(status));
+        actual_size += read_len;
+        if (status == APR_EOF)
+            break;
+    }
+
+    CuAssertIntEquals(tc, NR_OF_LOOPS * BUFSIZE, actual_size);
+#undef NR_OF_LOOPS
+#undef BUFSIZE
+}
+
 CuSuite *test_buckets(void)
 {
     CuSuite *suite = CuSuiteNew();
@@ -1243,6 +1586,13 @@
     SUITE_ADD_TEST(suite, test_random_eagain_in_response);
     SUITE_ADD_TEST(suite, test_dechunk_buckets);
     SUITE_ADD_TEST(suite, test_response_no_body_expected);
+    SUITE_ADD_TEST(suite, test_deflate_buckets);
+#if 0
+    /* This test for issue #152 takes a lot of time generating 4GB+ of random
+       data so it's disabled by default. */
+    SUITE_ADD_TEST(suite, test_deflate_4GBplus_buckets);
+#endif
+
 #if 0
     SUITE_ADD_TEST(suite, test_serf_default_read_iovec);
 #endif
diff -Nru serf-1.3.7/test/test_serf.h serf-1.3.8/test/test_serf.h
--- serf-1.3.7/test/test_serf.h	2013-06-23 04:43:58.000000000 -0400
+++ serf-1.3.8/test/test_serf.h	2014-10-19 14:24:37.000000000 -0400
@@ -108,8 +108,9 @@
     const char *serv_url;
     serf_connection_setup_t conn_setup;
 
-    /* An extra baton which can be freely used by tests. */
+    /* Extra batons which can be freely used by tests. */
     void *user_baton;
+    long user_baton_l;
 
     /* Flags that can be used to report situations, e.g. that a callback was
        called. */
diffstat for serf-1.3.7 serf-1.3.8

 CHANGES                                |    8 
 auth/auth_spnego_sspi.c                |    4 
 buckets/deflate_buckets.c              |   37 ++-
 buckets/ssl_buckets.c                  |    2 
 debian/changelog                       |   10 
 debian/patches/comment-style_r2443     |   19 +
 debian/patches/series                  |    2 
 debian/patches/test-memory-usage_r2445 |   61 +++++
 serf.h                                 |    2 
 test/test_buckets.c                    |  350 +++++++++++++++++++++++++++++++++
 test/test_serf.h                       |    3 
 11 files changed, 485 insertions(+), 13 deletions(-)

diff -Nru serf-1.3.7/auth/auth_spnego_sspi.c serf-1.3.8/auth/auth_spnego_sspi.c
--- serf-1.3.7/auth/auth_spnego_sspi.c	2014-02-04 14:41:14.000000000 -0500
+++ serf-1.3.8/auth/auth_spnego_sspi.c	2014-10-19 14:38:11.000000000 -0400
@@ -95,8 +95,8 @@
     }
 
     if (SecIsValidHandle(&ctx->sspi_credentials)) {
-        FreeCredentialsHandle(&ctx->sspi_context);
-        SecInvalidateHandle(&ctx->sspi_context);
+        FreeCredentialsHandle(&ctx->sspi_credentials);
+        SecInvalidateHandle(&ctx->sspi_credentials);
     }
 
     return APR_SUCCESS;
diff -Nru serf-1.3.7/buckets/deflate_buckets.c serf-1.3.8/buckets/deflate_buckets.c
--- serf-1.3.7/buckets/deflate_buckets.c	2011-06-23 22:03:57.000000000 -0400
+++ serf-1.3.8/buckets/deflate_buckets.c	2014-10-19 14:38:11.000000000 -0400
@@ -141,7 +141,6 @@
                                       const char **data, apr_size_t *len)
 {
     deflate_context_t *ctx = bucket->data;
-    unsigned long compCRC, compLen;
     apr_status_t status;
     const char *private_data;
     apr_size_t private_len;
@@ -186,17 +185,25 @@
             ctx->state++;
             break;
         case STATE_VERIFY:
+        {
+            unsigned long compCRC, compLen, actualLen;
+
             /* Do the checksum computation. */
             compCRC = getLong((unsigned char*)ctx->hdr_buffer);
             if (ctx->crc != compCRC) {
                 return SERF_ERROR_DECOMPRESSION_FAILED;
             }
             compLen = getLong((unsigned char*)ctx->hdr_buffer + 4);
-            if (ctx->zstream.total_out != compLen) {
+            /* The length in the trailer is module 2^32, so do the same for
+               the actual length. */
+            actualLen = ctx->zstream.total_out;
+            actualLen &= 0xFFFFFFFF;
+            if (actualLen != compLen) {
                 return SERF_ERROR_DECOMPRESSION_FAILED;
             }
             ctx->state++;
             break;
+        }
         case STATE_INIT:
             zRC = inflateInit2(&ctx->zstream, ctx->windowSize);
             if (zRC != Z_OK) {
@@ -264,10 +271,14 @@
                 ctx->zstream.next_in = (unsigned char*)private_data;
                 ctx->zstream.avail_in = private_len;
             }
-            zRC = Z_OK;
-            while (ctx->zstream.avail_in != 0) {
-                /* We're full, clear out our buffer, reset, and return. */
-                if (ctx->zstream.avail_out == 0) {
+
+            while (1) {
+
+                zRC = inflate(&ctx->zstream, Z_NO_FLUSH);
+
+                /* 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) {
                     serf_bucket_t *tmp;
                     ctx->zstream.next_out = ctx->buffer;
                     private_len = ctx->bufferSize - ctx->zstream.avail_out;
@@ -283,7 +294,6 @@
                     ctx->zstream.avail_out = ctx->bufferSize;
                     break;
                 }
-                zRC = inflate(&ctx->zstream, Z_NO_FLUSH);
 
                 if (zRC == Z_STREAM_END) {
                     serf_bucket_t *tmp;
@@ -330,9 +340,13 @@
 
                     break;
                 }
+
+                /* Any other error? */
                 if (zRC != Z_OK) {
                     return SERF_ERROR_DECOMPRESSION_FAILED;
                 }
+
+                /* As long as zRC == Z_OK, just keep looping. */
             }
             /* Okay, we've inflated.  Try to read. */
             status = serf_bucket_read(ctx->inflate_stream, requested, data,
@@ -340,8 +354,13 @@
             /* Hide EOF. */
             if (APR_STATUS_IS_EOF(status)) {
                 status = ctx->stream_status;
-                /* If our stream is finished too, return SUCCESS so
-                 * we'll iterate one more time.
+
+                /* If the inflation wasn't finished, return APR_SUCCESS. */
+                if (zRC != Z_STREAM_END)
+                    return APR_SUCCESS;
+
+                /* If our stream is finished too and all data was inflated,
+                 * return SUCCESS so we'll iterate one more time.
                  */
                 if (APR_STATUS_IS_EOF(status)) {
                     /* No more data to read from the stream, and everything
diff -Nru serf-1.3.7/buckets/ssl_buckets.c serf-1.3.8/buckets/ssl_buckets.c
--- serf-1.3.7/buckets/ssl_buckets.c	2014-08-05 22:24:00.000000000 -0400
+++ serf-1.3.8/buckets/ssl_buckets.c	2014-10-19 14:38:11.000000000 -0400
@@ -1317,7 +1317,9 @@
     ssl_ctx->pool = serf_bucket_allocator_get_pool(allocator);
     ssl_ctx->allocator = allocator;
 
+    /* Use the best possible protocol version, but disable the broken SSLv2/3 */
     ssl_ctx->ctx = SSL_CTX_new(SSLv23_client_method());
+    SSL_CTX_set_options(ssl_ctx->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
 
     SSL_CTX_set_client_cert_cb(ssl_ctx->ctx, ssl_need_client_cert);
     ssl_ctx->cached_cert = 0;
diff -Nru serf-1.3.7/CHANGES serf-1.3.8/CHANGES
--- serf-1.3.7/CHANGES	2014-08-11 11:17:02.000000000 -0400
+++ serf-1.3.8/CHANGES	2014-10-20 15:08:16.000000000 -0400
@@ -1,10 +1,18 @@
+Serf 1.3.8 [2014-10-20, from /tags/1.3.8, rxxxx]
+Fix issue #152: CRC calculation error for gzipped http reponses > 4GB.
+Fix issue #153: SSPI CredHandle not freed when APR pool is destroyed.
+Fix issue #154: Disable SSLv2 and SSLv3 as both or broken.
+
+
 Serf 1.3.7 [2014-08-11, from /tags/1.3.7, r2411]
   Handle NUL bytes in fields of an X.509 certificate. (r2393, r2399)
 
+
 Serf 1.3.6 [2014-06-09, from /tags/1.3.6, r2372]
   Revert r2319 from serf 1.3.5: this change was making serf call handle_response
     multiple times in case of an error response, leading to unexpected behavior.
 
+
 Serf 1.3.5 [2014-04-27, from /tags/1.3.5, r2355]
   Fix issue #125: no reverse lookup during Negotiate authentication for proxies.
   Fix a crash caused by incorrect reuse of the ssltunnel CONNECT request (r2316)
diff -Nru serf-1.3.7/debian/changelog serf-1.3.8/debian/changelog
--- serf-1.3.7/debian/changelog	2014-12-01 22:35:39.000000000 -0500
+++ serf-1.3.8/debian/changelog	2014-12-01 22:35:40.000000000 -0500
@@ -1,3 +1,13 @@
+serf (1.3.8-1) UNRELEASED; urgency=medium
+
+  * New upstream release
+    - Disable SSLv2 and SSLv3
+  * Backport r2445 from upstream to fix potential memory allocation failures
+    in the test suite.
+  * Backport r2443 from upstream to fix a compile failure in the test suite.
+
+ -- James McCoy <jamessan@debian.org>  Mon, 01 Dec 2014 22:11:04 -0500
+
 serf (1.3.7-3) unstable; urgency=medium
 
   * Specify the proper prefix/libdir when building libserf-1.pc.
diff -Nru serf-1.3.7/debian/patches/comment-style_r2443 serf-1.3.8/debian/patches/comment-style_r2443
--- serf-1.3.7/debian/patches/comment-style_r2443	1969-12-31 19:00:00.000000000 -0500
+++ serf-1.3.8/debian/patches/comment-style_r2443	2014-12-01 22:35:40.000000000 -0500
@@ -0,0 +1,19 @@
+Subject: Correct comment style
+Description:
+ * test/test_buckets.c
+   (deflate_compress): Correct comment style not supported by strict
+   compilers
+Origin: upstream, r2443
+--- a/test/test_buckets.c
++++ b/test/test_buckets.c
+@@ -1232,9 +1232,9 @@
+ 
+     /* The largest buffer we should need is 0.1% larger than the
+        uncompressed data, + 12 bytes. This info comes from zlib.h.
++       buf_size = orig_len + (orig_len / 1000) + 12;
+        Note: This isn't sufficient when using Z_NO_FLUSH and extremely compressed
+        data. Use a buffer bigger than what we need. */
+-//    buf_size = orig_len + (orig_len / 1000) + 12;
+     buf_size = 100000;
+ 
+     write_buf = apr_palloc(pool, buf_size);
diff -Nru serf-1.3.7/debian/patches/series serf-1.3.8/debian/patches/series
--- serf-1.3.7/debian/patches/series	2014-12-01 22:35:39.000000000 -0500
+++ serf-1.3.8/debian/patches/series	2014-12-01 22:35:40.000000000 -0500
@@ -1 +1,3 @@
 libtool
+test-memory-usage_r2445
+comment-style_r2443
diff -Nru serf-1.3.7/debian/patches/test-memory-usage_r2445 serf-1.3.8/debian/patches/test-memory-usage_r2445
--- serf-1.3.7/debian/patches/test-memory-usage_r2445	1969-12-31 19:00:00.000000000 -0500
+++ serf-1.3.8/debian/patches/test-memory-usage_r2445	2014-12-01 22:35:40.000000000 -0500
@@ -0,0 +1,61 @@
+Subject: Reduce memory usage by deflate bucket test.
+Origin: upstream, r2445
+--- a/test/test_buckets.c
++++ b/test/test_buckets.c
+@@ -1309,12 +1309,12 @@
+                           expected_len);
+ }
+ 
+-static void deflate_buckets(CuTest *tc, int nr_of_loops)
++static void deflate_buckets(CuTest *tc, int nr_of_loops, apr_pool_t *pool)
+ {
+     const char *msg = "12345678901234567890123456789012345678901234567890";
+ 
+     test_baton_t *tb = tc->testBaton;
+-    serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(tb->pool, NULL,
++    serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(pool, NULL,
+                                                               NULL);
+     z_stream zdestr;
+     int i;
+@@ -1333,8 +1333,8 @@
+     {
+         serf_config_t *config;
+ 
+-        serf_context_t *ctx = serf_context_create(tb->pool);
+-        /* status = */ serf__config_store_get_config(ctx, NULL, &config, tb->pool);
++        serf_context_t *ctx = serf_context_create(pool);
++        /* status = */ serf__config_store_get_config(ctx, NULL, &config, pool);
+ 
+         serf_bucket_set_config(defbkt, config);
+     }
+@@ -1356,11 +1356,11 @@
+         if (i == nr_of_loops - 1) {
+             CuAssertIntEquals(tc, APR_SUCCESS,
+                               deflate_compress(&data, &len, &zdestr, msg,
+-                                               strlen(msg), 1, tb->pool));
++                                               strlen(msg), 1, pool));
+         } else {
+             CuAssertIntEquals(tc, APR_SUCCESS,
+                               deflate_compress(&data, &len, &zdestr, msg,
+-                                               strlen(msg), 0, tb->pool));
++                                               strlen(msg), 0, pool));
+         }
+ 
+         if (len == 0)
+@@ -1378,10 +1378,15 @@
+ static void test_deflate_buckets(CuTest *tc)
+ {
+     int i;
++    apr_pool_t *iterpool;
++    test_baton_t *tb = tc->testBaton;
+ 
++    apr_pool_create(&iterpool, tb->pool);
+     for (i = 1; i < 1000; i++) {
+-        deflate_buckets(tc, i);
++        apr_pool_clear(iterpool);
++        deflate_buckets(tc, i, iterpool);
+     }
++    apr_pool_destroy(iterpool);
+ }
+ 
+ static apr_status_t discard_data(serf_bucket_t *bkt,
diff -Nru serf-1.3.7/serf.h serf-1.3.8/serf.h
--- serf-1.3.7/serf.h	2014-08-04 14:11:28.000000000 -0400
+++ serf-1.3.8/serf.h	2014-10-19 14:20:09.000000000 -0400
@@ -1062,7 +1062,7 @@
 /* Version info */
 #define SERF_MAJOR_VERSION 1
 #define SERF_MINOR_VERSION 3
-#define SERF_PATCH_VERSION 7
+#define SERF_PATCH_VERSION 8
 
 /* Version number string */
 #define SERF_VERSION_STRING APR_STRINGIFY(SERF_MAJOR_VERSION) "." \
diff -Nru serf-1.3.7/test/test_buckets.c serf-1.3.8/test/test_buckets.c
diff -Nru serf-1.3.7/test/test_serf.h serf-1.3.8/test/test_serf.h

Reply to: