1
1
libssh2/src/comp.c

367 строки
10 KiB
C
Исходник Обычный вид История

/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2010-2014, Daniel Stenberg <daniel@haxx.se>
2004-12-07 21:17:20 +00:00
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the copyright holder nor the names
* of any other contributors may be used to endorse or
* promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
#include "libssh2_priv.h"
#ifdef LIBSSH2_HAVE_ZLIB
# include <zlib.h>
#endif
2004-12-07 21:17:20 +00:00
#include "comp.h"
2004-12-07 21:17:20 +00:00
/* ********
* none *
******** */
2004-12-07 21:17:20 +00:00
/*
* comp_method_none_comp
*
2004-12-07 21:17:20 +00:00
* Minimalist compression: Absolutely none
*/
static int
comp_method_none_comp(LIBSSH2_SESSION *session,
unsigned char *dest,
size_t *dest_len,
const unsigned char *src,
size_t src_len,
void **abstract)
{
(void) session;
(void) abstract;
(void) dest;
(void) dest_len;
(void) src;
(void) src_len;
return 0;
}
/*
* comp_method_none_decomp
*
* Minimalist decompression: Absolutely none
*/
static int
comp_method_none_decomp(LIBSSH2_SESSION * session,
unsigned char **dest,
size_t *dest_len,
size_t payload_limit,
const unsigned char *src,
size_t src_len, void **abstract)
2004-12-07 21:17:20 +00:00
{
(void) session;
(void) payload_limit;
(void) abstract;
*dest = (unsigned char *) src;
*dest_len = src_len;
return 0;
2004-12-07 21:17:20 +00:00
}
2004-12-07 21:17:20 +00:00
static const LIBSSH2_COMP_METHOD comp_method_none = {
"none",
0, /* not really compressing */
0, /* isn't used in userauth, go figure */
NULL,
comp_method_none_comp,
comp_method_none_decomp,
NULL
2004-12-07 21:17:20 +00:00
};
#ifdef LIBSSH2_HAVE_ZLIB
/* ********
* zlib *
******** */
2004-12-07 21:17:20 +00:00
/* Memory management wrappers
2004-12-07 21:17:20 +00:00
* Yes, I realize we're doing a callback to a callback,
* Deal...
*/
static voidpf
comp_method_zlib_alloc(voidpf opaque, uInt items, uInt size)
2004-12-07 21:17:20 +00:00
{
LIBSSH2_SESSION *session = (LIBSSH2_SESSION *) opaque;
2004-12-07 21:17:20 +00:00
return (voidpf) LIBSSH2_ALLOC(session, items * size);
2004-12-07 21:17:20 +00:00
}
static void
comp_method_zlib_free(voidpf opaque, voidpf address)
2004-12-07 21:17:20 +00:00
{
LIBSSH2_SESSION *session = (LIBSSH2_SESSION *) opaque;
2004-12-07 21:17:20 +00:00
LIBSSH2_FREE(session, address);
2004-12-07 21:17:20 +00:00
}
2004-12-07 21:17:20 +00:00
/* libssh2_comp_method_zlib_init
2004-12-07 21:17:20 +00:00
* All your bandwidth are belong to us (so save some)
*/
static int
comp_method_zlib_init(LIBSSH2_SESSION * session, int compr,
void **abstract)
2004-12-07 21:17:20 +00:00
{
z_stream *strm;
int status;
strm = LIBSSH2_CALLOC(session, sizeof(z_stream));
if (!strm) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"zlib compression/decompression");
}
strm->opaque = (voidpf) session;
strm->zalloc = (alloc_func) comp_method_zlib_alloc;
strm->zfree = (free_func) comp_method_zlib_free;
if (compr) {
/* deflate */
status = deflateInit(strm, Z_DEFAULT_COMPRESSION);
} else {
/* inflate */
status = inflateInit(strm);
}
if (status != Z_OK) {
LIBSSH2_FREE(session, strm);
2010-11-03 14:42:44 +01:00
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"unhandled zlib error %d", status);
return LIBSSH2_ERROR_COMPRESS;
}
*abstract = strm;
return LIBSSH2_ERROR_NONE;
2004-12-07 21:17:20 +00:00
}
/*
* libssh2_comp_method_zlib_comp
*
* Compresses source to destination. Without allocation.
2004-12-07 21:17:20 +00:00
*/
static int
comp_method_zlib_comp(LIBSSH2_SESSION *session,
unsigned char *dest,
/* dest_len is a pointer to allow this function to
update it with the final actual size used */
size_t *dest_len,
const unsigned char *src,
size_t src_len,
void **abstract)
2004-12-07 21:17:20 +00:00
{
z_stream *strm = *abstract;
int out_maxlen = *dest_len;
int status;
strm->next_in = (unsigned char *) src;
strm->avail_in = src_len;
strm->next_out = dest;
strm->avail_out = out_maxlen;
status = deflate(strm, Z_PARTIAL_FLUSH);
if ((status == Z_OK) && (strm->avail_out > 0)) {
*dest_len = out_maxlen - strm->avail_out;
return 0;
2010-11-03 14:42:44 +01:00
}
_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");
2004-12-07 21:17:20 +00:00
}
/*
* libssh2_comp_method_zlib_decomp
*
* Decompresses source to destination. Allocates the output memory.
*/
static int
comp_method_zlib_decomp(LIBSSH2_SESSION * session,
unsigned char **dest,
size_t *dest_len,
size_t payload_limit,
const unsigned char *src,
size_t src_len, void **abstract)
{
z_stream *strm = *abstract;
/* A short-term alloc of a full data chunk is better than a series of
reallocs */
char *out;
int out_maxlen = 4 * src_len;
/* If strm is null, then we have not yet been initialized. */
if (strm == NULL)
return _libssh2_error(session, LIBSSH2_ERROR_COMPRESS,
2014-02-18 23:46:25 +01:00
"decompression uninitialized");;
/* In practice they never come smaller than this */
if (out_maxlen < 25)
out_maxlen = 25;
if (out_maxlen > (int) payload_limit)
out_maxlen = payload_limit;
strm->next_in = (unsigned char *) src;
strm->avail_in = src_len;
strm->next_out = (unsigned char *) LIBSSH2_ALLOC(session, out_maxlen);
out = (char *) strm->next_out;
strm->avail_out = out_maxlen;
if (!strm->next_out)
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate decompression buffer");
comp_method_zlib_decomp: handle Z_BUF_ERROR when inflating When using libssh2 to perform an SFTP file transfer from the "JSCAPE MFT Server" (http://www.jscape.com) the transfer failed. The default JSCAPE configuration is to enforce zlib compression on SSH2 sessions so the session was compressed. The relevant part of the debug trace contained: [libssh2] 1.052750 Transport: unhandled zlib error -5 [libssh2] 1.052750 Failure Event: -29 - decompression failure The trace comes from comp_method_zlib_decomp() in comp.c. The "unhandled zlib error -5" is the status returned from the zlib function inflate(). The -5 status corresponds to "Z_BUF_ERROR". The inflate() function takes a pointer to a z_stream structure and "inflates" (decompresses) as much as it can. The relevant fields of the z_stream structure are: next_in - pointer to the input buffer containing compressed data avail_in - the number of bytes available at next_in next_out - pointer to the output buffer to be filled with uncompressed data avail_out - how much space available at next_out To decompress data you set up a z_stream struct with the relevant fields filled in and pass it to inflate(). On return the fields will have been updated so next_in and avail_in show how much compressed data is yet to be processed and next_out and avail_out show how much space is left in the output buffer. If the supplied output buffer is too small then on return there will be compressed data yet to be processed (avail_in != 0) and inflate() will return Z_OK. In this case the output buffer must be grown, avail_out updated and inflate() called again. If the supplied output buffer was big enough then on return the compressed data will have been exhausted (avail_in == 0) and inflate() will return Z_OK, so the data has all been uncompressed. There is a corner case where inflate() makes no progress. That is, there may be unprocessed compressed data and space available in the output buffer and yet the function does nothing. In this case inflate() will return Z_BUF_ERROR. From the zlib documentation and the source code it is not clear under what circumstances this happens. It could be that it needs to write multiple bytes (all in one go) from its internal state to the output buffer before processing the next chunk of input but but can't because there is not enough space (though my guesses as to the cause are not really relevant). Recovery from Z_BUF_ERROR is pretty simple - just grow the output buffer, update avail_out and call inflate() again. The comp_method_zlib_decomp() function does not handle the case when inflate() returns Z_BUF_ERROR. It treats it as a non-recoverable error and basically aborts the session. Fixes #240
2012-06-14 16:05:23 +02:00
/* Loop until it's all inflated or hit error */
for (;;) {
int status;
comp_method_zlib_decomp: handle Z_BUF_ERROR when inflating When using libssh2 to perform an SFTP file transfer from the "JSCAPE MFT Server" (http://www.jscape.com) the transfer failed. The default JSCAPE configuration is to enforce zlib compression on SSH2 sessions so the session was compressed. The relevant part of the debug trace contained: [libssh2] 1.052750 Transport: unhandled zlib error -5 [libssh2] 1.052750 Failure Event: -29 - decompression failure The trace comes from comp_method_zlib_decomp() in comp.c. The "unhandled zlib error -5" is the status returned from the zlib function inflate(). The -5 status corresponds to "Z_BUF_ERROR". The inflate() function takes a pointer to a z_stream structure and "inflates" (decompresses) as much as it can. The relevant fields of the z_stream structure are: next_in - pointer to the input buffer containing compressed data avail_in - the number of bytes available at next_in next_out - pointer to the output buffer to be filled with uncompressed data avail_out - how much space available at next_out To decompress data you set up a z_stream struct with the relevant fields filled in and pass it to inflate(). On return the fields will have been updated so next_in and avail_in show how much compressed data is yet to be processed and next_out and avail_out show how much space is left in the output buffer. If the supplied output buffer is too small then on return there will be compressed data yet to be processed (avail_in != 0) and inflate() will return Z_OK. In this case the output buffer must be grown, avail_out updated and inflate() called again. If the supplied output buffer was big enough then on return the compressed data will have been exhausted (avail_in == 0) and inflate() will return Z_OK, so the data has all been uncompressed. There is a corner case where inflate() makes no progress. That is, there may be unprocessed compressed data and space available in the output buffer and yet the function does nothing. In this case inflate() will return Z_BUF_ERROR. From the zlib documentation and the source code it is not clear under what circumstances this happens. It could be that it needs to write multiple bytes (all in one go) from its internal state to the output buffer before processing the next chunk of input but but can't because there is not enough space (though my guesses as to the cause are not really relevant). Recovery from Z_BUF_ERROR is pretty simple - just grow the output buffer, update avail_out and call inflate() again. The comp_method_zlib_decomp() function does not handle the case when inflate() returns Z_BUF_ERROR. It treats it as a non-recoverable error and basically aborts the session. Fixes #240
2012-06-14 16:05:23 +02:00
size_t out_ofs;
char *newout;
status = inflate(strm, Z_PARTIAL_FLUSH);
comp_method_zlib_decomp: handle Z_BUF_ERROR when inflating When using libssh2 to perform an SFTP file transfer from the "JSCAPE MFT Server" (http://www.jscape.com) the transfer failed. The default JSCAPE configuration is to enforce zlib compression on SSH2 sessions so the session was compressed. The relevant part of the debug trace contained: [libssh2] 1.052750 Transport: unhandled zlib error -5 [libssh2] 1.052750 Failure Event: -29 - decompression failure The trace comes from comp_method_zlib_decomp() in comp.c. The "unhandled zlib error -5" is the status returned from the zlib function inflate(). The -5 status corresponds to "Z_BUF_ERROR". The inflate() function takes a pointer to a z_stream structure and "inflates" (decompresses) as much as it can. The relevant fields of the z_stream structure are: next_in - pointer to the input buffer containing compressed data avail_in - the number of bytes available at next_in next_out - pointer to the output buffer to be filled with uncompressed data avail_out - how much space available at next_out To decompress data you set up a z_stream struct with the relevant fields filled in and pass it to inflate(). On return the fields will have been updated so next_in and avail_in show how much compressed data is yet to be processed and next_out and avail_out show how much space is left in the output buffer. If the supplied output buffer is too small then on return there will be compressed data yet to be processed (avail_in != 0) and inflate() will return Z_OK. In this case the output buffer must be grown, avail_out updated and inflate() called again. If the supplied output buffer was big enough then on return the compressed data will have been exhausted (avail_in == 0) and inflate() will return Z_OK, so the data has all been uncompressed. There is a corner case where inflate() makes no progress. That is, there may be unprocessed compressed data and space available in the output buffer and yet the function does nothing. In this case inflate() will return Z_BUF_ERROR. From the zlib documentation and the source code it is not clear under what circumstances this happens. It could be that it needs to write multiple bytes (all in one go) from its internal state to the output buffer before processing the next chunk of input but but can't because there is not enough space (though my guesses as to the cause are not really relevant). Recovery from Z_BUF_ERROR is pretty simple - just grow the output buffer, update avail_out and call inflate() again. The comp_method_zlib_decomp() function does not handle the case when inflate() returns Z_BUF_ERROR. It treats it as a non-recoverable error and basically aborts the session. Fixes #240
2012-06-14 16:05:23 +02:00
if (status == Z_OK) {
if (strm->avail_out > 0)
/* status is OK and the output buffer has not been exhausted so we're done */
comp_method_zlib_decomp: handle Z_BUF_ERROR when inflating When using libssh2 to perform an SFTP file transfer from the "JSCAPE MFT Server" (http://www.jscape.com) the transfer failed. The default JSCAPE configuration is to enforce zlib compression on SSH2 sessions so the session was compressed. The relevant part of the debug trace contained: [libssh2] 1.052750 Transport: unhandled zlib error -5 [libssh2] 1.052750 Failure Event: -29 - decompression failure The trace comes from comp_method_zlib_decomp() in comp.c. The "unhandled zlib error -5" is the status returned from the zlib function inflate(). The -5 status corresponds to "Z_BUF_ERROR". The inflate() function takes a pointer to a z_stream structure and "inflates" (decompresses) as much as it can. The relevant fields of the z_stream structure are: next_in - pointer to the input buffer containing compressed data avail_in - the number of bytes available at next_in next_out - pointer to the output buffer to be filled with uncompressed data avail_out - how much space available at next_out To decompress data you set up a z_stream struct with the relevant fields filled in and pass it to inflate(). On return the fields will have been updated so next_in and avail_in show how much compressed data is yet to be processed and next_out and avail_out show how much space is left in the output buffer. If the supplied output buffer is too small then on return there will be compressed data yet to be processed (avail_in != 0) and inflate() will return Z_OK. In this case the output buffer must be grown, avail_out updated and inflate() called again. If the supplied output buffer was big enough then on return the compressed data will have been exhausted (avail_in == 0) and inflate() will return Z_OK, so the data has all been uncompressed. There is a corner case where inflate() makes no progress. That is, there may be unprocessed compressed data and space available in the output buffer and yet the function does nothing. In this case inflate() will return Z_BUF_ERROR. From the zlib documentation and the source code it is not clear under what circumstances this happens. It could be that it needs to write multiple bytes (all in one go) from its internal state to the output buffer before processing the next chunk of input but but can't because there is not enough space (though my guesses as to the cause are not really relevant). Recovery from Z_BUF_ERROR is pretty simple - just grow the output buffer, update avail_out and call inflate() again. The comp_method_zlib_decomp() function does not handle the case when inflate() returns Z_BUF_ERROR. It treats it as a non-recoverable error and basically aborts the session. Fixes #240
2012-06-14 16:05:23 +02:00
break;
} else if (status == Z_BUF_ERROR) {
/* the input data has been exhausted so we are done */
break;
comp_method_zlib_decomp: handle Z_BUF_ERROR when inflating When using libssh2 to perform an SFTP file transfer from the "JSCAPE MFT Server" (http://www.jscape.com) the transfer failed. The default JSCAPE configuration is to enforce zlib compression on SSH2 sessions so the session was compressed. The relevant part of the debug trace contained: [libssh2] 1.052750 Transport: unhandled zlib error -5 [libssh2] 1.052750 Failure Event: -29 - decompression failure The trace comes from comp_method_zlib_decomp() in comp.c. The "unhandled zlib error -5" is the status returned from the zlib function inflate(). The -5 status corresponds to "Z_BUF_ERROR". The inflate() function takes a pointer to a z_stream structure and "inflates" (decompresses) as much as it can. The relevant fields of the z_stream structure are: next_in - pointer to the input buffer containing compressed data avail_in - the number of bytes available at next_in next_out - pointer to the output buffer to be filled with uncompressed data avail_out - how much space available at next_out To decompress data you set up a z_stream struct with the relevant fields filled in and pass it to inflate(). On return the fields will have been updated so next_in and avail_in show how much compressed data is yet to be processed and next_out and avail_out show how much space is left in the output buffer. If the supplied output buffer is too small then on return there will be compressed data yet to be processed (avail_in != 0) and inflate() will return Z_OK. In this case the output buffer must be grown, avail_out updated and inflate() called again. If the supplied output buffer was big enough then on return the compressed data will have been exhausted (avail_in == 0) and inflate() will return Z_OK, so the data has all been uncompressed. There is a corner case where inflate() makes no progress. That is, there may be unprocessed compressed data and space available in the output buffer and yet the function does nothing. In this case inflate() will return Z_BUF_ERROR. From the zlib documentation and the source code it is not clear under what circumstances this happens. It could be that it needs to write multiple bytes (all in one go) from its internal state to the output buffer before processing the next chunk of input but but can't because there is not enough space (though my guesses as to the cause are not really relevant). Recovery from Z_BUF_ERROR is pretty simple - just grow the output buffer, update avail_out and call inflate() again. The comp_method_zlib_decomp() function does not handle the case when inflate() returns Z_BUF_ERROR. It treats it as a non-recoverable error and basically aborts the session. Fixes #240
2012-06-14 16:05:23 +02:00
} else {
/* error state */
LIBSSH2_FREE(session, out);
2010-11-03 14:42:44 +01:00
_libssh2_debug(session, LIBSSH2_TRACE_TRANS,
"unhandled zlib error %d", status);
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"decompression failure");
}
if (out_maxlen >= (int) payload_limit) {
comp_method_zlib_decomp: handle Z_BUF_ERROR when inflating When using libssh2 to perform an SFTP file transfer from the "JSCAPE MFT Server" (http://www.jscape.com) the transfer failed. The default JSCAPE configuration is to enforce zlib compression on SSH2 sessions so the session was compressed. The relevant part of the debug trace contained: [libssh2] 1.052750 Transport: unhandled zlib error -5 [libssh2] 1.052750 Failure Event: -29 - decompression failure The trace comes from comp_method_zlib_decomp() in comp.c. The "unhandled zlib error -5" is the status returned from the zlib function inflate(). The -5 status corresponds to "Z_BUF_ERROR". The inflate() function takes a pointer to a z_stream structure and "inflates" (decompresses) as much as it can. The relevant fields of the z_stream structure are: next_in - pointer to the input buffer containing compressed data avail_in - the number of bytes available at next_in next_out - pointer to the output buffer to be filled with uncompressed data avail_out - how much space available at next_out To decompress data you set up a z_stream struct with the relevant fields filled in and pass it to inflate(). On return the fields will have been updated so next_in and avail_in show how much compressed data is yet to be processed and next_out and avail_out show how much space is left in the output buffer. If the supplied output buffer is too small then on return there will be compressed data yet to be processed (avail_in != 0) and inflate() will return Z_OK. In this case the output buffer must be grown, avail_out updated and inflate() called again. If the supplied output buffer was big enough then on return the compressed data will have been exhausted (avail_in == 0) and inflate() will return Z_OK, so the data has all been uncompressed. There is a corner case where inflate() makes no progress. That is, there may be unprocessed compressed data and space available in the output buffer and yet the function does nothing. In this case inflate() will return Z_BUF_ERROR. From the zlib documentation and the source code it is not clear under what circumstances this happens. It could be that it needs to write multiple bytes (all in one go) from its internal state to the output buffer before processing the next chunk of input but but can't because there is not enough space (though my guesses as to the cause are not really relevant). Recovery from Z_BUF_ERROR is pretty simple - just grow the output buffer, update avail_out and call inflate() again. The comp_method_zlib_decomp() function does not handle the case when inflate() returns Z_BUF_ERROR. It treats it as a non-recoverable error and basically aborts the session. Fixes #240
2012-06-14 16:05:23 +02:00
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;
comp_method_zlib_decomp: handle Z_BUF_ERROR when inflating When using libssh2 to perform an SFTP file transfer from the "JSCAPE MFT Server" (http://www.jscape.com) the transfer failed. The default JSCAPE configuration is to enforce zlib compression on SSH2 sessions so the session was compressed. The relevant part of the debug trace contained: [libssh2] 1.052750 Transport: unhandled zlib error -5 [libssh2] 1.052750 Failure Event: -29 - decompression failure The trace comes from comp_method_zlib_decomp() in comp.c. The "unhandled zlib error -5" is the status returned from the zlib function inflate(). The -5 status corresponds to "Z_BUF_ERROR". The inflate() function takes a pointer to a z_stream structure and "inflates" (decompresses) as much as it can. The relevant fields of the z_stream structure are: next_in - pointer to the input buffer containing compressed data avail_in - the number of bytes available at next_in next_out - pointer to the output buffer to be filled with uncompressed data avail_out - how much space available at next_out To decompress data you set up a z_stream struct with the relevant fields filled in and pass it to inflate(). On return the fields will have been updated so next_in and avail_in show how much compressed data is yet to be processed and next_out and avail_out show how much space is left in the output buffer. If the supplied output buffer is too small then on return there will be compressed data yet to be processed (avail_in != 0) and inflate() will return Z_OK. In this case the output buffer must be grown, avail_out updated and inflate() called again. If the supplied output buffer was big enough then on return the compressed data will have been exhausted (avail_in == 0) and inflate() will return Z_OK, so the data has all been uncompressed. There is a corner case where inflate() makes no progress. That is, there may be unprocessed compressed data and space available in the output buffer and yet the function does nothing. In this case inflate() will return Z_BUF_ERROR. From the zlib documentation and the source code it is not clear under what circumstances this happens. It could be that it needs to write multiple bytes (all in one go) from its internal state to the output buffer before processing the next chunk of input but but can't because there is not enough space (though my guesses as to the cause are not really relevant). Recovery from Z_BUF_ERROR is pretty simple - just grow the output buffer, update avail_out and call inflate() again. The comp_method_zlib_decomp() function does not handle the case when inflate() returns Z_BUF_ERROR. It treats it as a non-recoverable error and basically aborts the session. Fixes #240
2012-06-14 16:05:23 +02:00
newout = LIBSSH2_REALLOC(session, out, out_maxlen);
if (!newout) {
LIBSSH2_FREE(session, out);
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to expand decompression buffer");
}
out = newout;
strm->next_out = (unsigned char *) out + out_ofs;
strm->avail_out = out_maxlen - out_ofs;
}
*dest = (unsigned char *) out;
*dest_len = out_maxlen - strm->avail_out;
return 0;
}
2004-12-07 21:17:20 +00:00
/* libssh2_comp_method_zlib_dtor
2004-12-07 21:17:20 +00:00
* All done, no more compression for you
*/
static int
comp_method_zlib_dtor(LIBSSH2_SESSION *session, int compr, void **abstract)
2004-12-07 21:17:20 +00:00
{
z_stream *strm = *abstract;
2004-12-07 21:17:20 +00:00
if (strm) {
if (compr)
deflateEnd(strm);
else
inflateEnd(strm);
LIBSSH2_FREE(session, strm);
}
2004-12-07 21:17:20 +00:00
*abstract = NULL;
return 0;
2004-12-07 21:17:20 +00:00
}
static const LIBSSH2_COMP_METHOD comp_method_zlib = {
"zlib",
1, /* yes, this compresses */
1, /* do compression during userauth */
comp_method_zlib_init,
comp_method_zlib_comp,
comp_method_zlib_decomp,
comp_method_zlib_dtor,
};
static const LIBSSH2_COMP_METHOD comp_method_zlib_openssh = {
"zlib@openssh.com",
1, /* yes, this compresses */
0, /* don't use compression during userauth */
comp_method_zlib_init,
comp_method_zlib_comp,
comp_method_zlib_decomp,
comp_method_zlib_dtor,
2004-12-07 21:17:20 +00:00
};
#endif /* LIBSSH2_HAVE_ZLIB */
/* If compression is enabled by the API, then this array is used which then
may allow compression if zlib is available at build time */
static const LIBSSH2_COMP_METHOD *comp_methods[] = {
2004-12-07 21:17:20 +00:00
#ifdef LIBSSH2_HAVE_ZLIB
&comp_method_zlib,
&comp_method_zlib_openssh,
2004-12-07 21:17:20 +00:00
#endif /* LIBSSH2_HAVE_ZLIB */
&comp_method_none,
NULL
2004-12-07 21:17:20 +00:00
};
/* If compression is disabled by the API, then this array is used */
static const LIBSSH2_COMP_METHOD *no_comp_methods[] = {
&comp_method_none,
NULL
};
const LIBSSH2_COMP_METHOD **
_libssh2_comp_methods(LIBSSH2_SESSION *session)
{
if(session->flag.compress)
return comp_methods;
else
return no_comp_methods;
2004-12-07 21:17:20 +00:00
}