Two additional minor improviments on src/comp.c. See the commits messages from the attached patchs for the details.
>From 2e52715df004759e42aa757d1236e4ac7c7fdebd Mon Sep 17 00:00:00 2001 From: Salvador <sfand...@yahoo.com> Date: Tue, 15 Oct 2013 13:07:00 +0200 Subject: [PATCH 4/5] Improve buffer growing algorithm in comp_method_zlib_decomp.
The old algorithm was O(N^2), causing lots and lots of reallocations when highly compressed data was transferred. This patch implements a simpler one that just doubles the buffer size everytime it is exhausted. It results in O(N) complexity. Also a smaller inflate ratio is used to calculate the initial size (x4). Signed-off-by: Salvador <sfand...@yahoo.com> --- src/comp.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/src/comp.c b/src/comp.c index c9226ed..7281418 100644 --- a/src/comp.c +++ b/src/comp.c @@ -226,8 +226,7 @@ comp_method_zlib_decomp(LIBSSH2_SESSION * session, /* A short-term alloc of a full data chunk is better than a series of reallocs */ char *out; - int out_maxlen = 8 * src_len; - int limiter = 0; + int out_maxlen = 4 * src_len; /* If strm is null, then we have not yet been initialized. */ if (strm == NULL) @@ -252,7 +251,7 @@ comp_method_zlib_decomp(LIBSSH2_SESSION * session, /* Loop until it's all inflated or hit error */ for (;;) { - int status, grow_size; + int status; size_t out_ofs; char *newout; @@ -274,22 +273,15 @@ comp_method_zlib_decomp(LIBSSH2_SESSION * session, "decompression failure"); } - /* If we get here we need to grow the output buffer and try again */ - out_ofs = out_maxlen - strm->avail_out; - if (strm->avail_in) { - grow_size = strm->avail_in * 8; - } else { - /* Not sure how much to grow by */ - grow_size = 32; - } - out_maxlen += grow_size; - - if ((out_maxlen > (int) payload_limit) && limiter++) { + if (out_maxlen >= (int) payload_limit) { LIBSSH2_FREE(session, out); return _libssh2_error(session, LIBSSH2_ERROR_ZLIB, "Excessive growth in decompression phase"); } + /* If we get here we need to grow the output buffer and try again */ + out_ofs = out_maxlen - strm->avail_out; + out_maxlen *= 2; newout = LIBSSH2_REALLOC(session, out, out_maxlen); if (!newout) { LIBSSH2_FREE(session, out); @@ -298,7 +290,7 @@ comp_method_zlib_decomp(LIBSSH2_SESSION * session, } out = newout; strm->next_out = (unsigned char *) out + out_ofs; - strm->avail_out += grow_size; + strm->avail_out = out_maxlen - out_ofs; } *dest = (unsigned char *) out; -- 1.8.3.2
>From 98f38a144350e90f06581fb7a149ca926df322e2 Mon Sep 17 00:00:00 2001 From: Salvador <sfand...@yahoo.com> Date: Wed, 16 Oct 2013 09:44:18 +0200 Subject: [PATCH 5/5] Fix zlib deflate usage Deflate may return Z_OK even when not all data has been compressed if the output buffer becomes full. In practice this is very unlikely to happen because the output buffer size is always some KBs larger than the size of the data passed for compression from the upper layers and I think that zlib never expands the data so much, even on the worst cases. Anyway, this patch plays on the safe side checking that the output buffer is not exhausted. Signed-off-by: Salvador <sfand...@yahoo.com> --- src/comp.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/comp.c b/src/comp.c index 7281418..79b8ee2 100644 --- a/src/comp.c +++ b/src/comp.c @@ -198,15 +198,14 @@ comp_method_zlib_comp(LIBSSH2_SESSION *session, status = deflate(strm, Z_PARTIAL_FLUSH); - if (status != Z_OK) { - _libssh2_debug(session, LIBSSH2_TRACE_TRANS, - "unhandled zlib compression error %d", status); - return _libssh2_error(session, LIBSSH2_ERROR_ZLIB, - "compression failure"); + if ((status == Z_OK) && (strm->avail_out > 0)) { + *dest_len = out_maxlen - strm->avail_out; + return 0; } - *dest_len = out_maxlen - strm->avail_out; - return 0; + _libssh2_debug(session, LIBSSH2_TRACE_TRANS, + "unhandled zlib compression error %d, avail_out", status, strm->avail_out); + return _libssh2_error(session, LIBSSH2_ERROR_ZLIB, "compression failure"); } /* -- 1.8.3.2
_______________________________________________ libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel