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

Bug#771758: marked as done (unblock: serf/1.3.8-1)



Your message dated Fri, 05 Dec 2014 05:41:23 +0000
with message-id <1417758083.10998.40.camel@adam-barratt.org.uk>
and subject line Re: Bug#771758: unblock (pre-approval): serf/1.3.8-1
has caused the Debian Bug report #771758,
regarding unblock: serf/1.3.8-1
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
771758: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=771758
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
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

--- End Message ---
--- Begin Message ---
On Thu, 2014-12-04 at 19:55 -0500, James McCoy wrote:
> Control: tags -1 - moreinfo
> Control: retitle -1 unblock: serf/1.3.8-1
> 
> On Thu, Dec 04, 2014 at 07:58:20AM +0000, Adam D. Barratt wrote:
> > On 2014-12-02 3:38, James McCoy wrote:
> > >Please unblock package serf
> > 
> > Please go ahead, and remove the moreinfo tag once the package has been
> > accepted.
> 
> Uploaded and accepted.  Thanks.

Unblocked, thanks.

Regards,

Adam

--- End Message ---

Reply to: