Fix zlib compression when internal buffer not empty
Этот коммит содержится в:
родитель
5f2864c0b4
Коммит
2c5c54e999
2
README
2
README
@ -4,6 +4,8 @@ libssh2 - SSH2 library
|
|||||||
Version 0.6
|
Version 0.6
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
Fix zlib compression issue when internal buffer state misses partial sync.
|
||||||
|
|
||||||
Fix segfault when libssh2_session_methods() is called prior to session_startup().
|
Fix segfault when libssh2_session_methods() is called prior to session_startup().
|
||||||
|
|
||||||
Fixed client to server channel windowing. Pervent send queue overruns.
|
Fixed client to server channel windowing. Pervent send queue overruns.
|
||||||
|
48
src/comp.c
48
src/comp.c
@ -136,12 +136,12 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session, int compress,
|
|||||||
z_stream *strm = *abstract;
|
z_stream *strm = *abstract;
|
||||||
/* A short-term alloc of a full data chunk is better than a series of reallocs */
|
/* A short-term alloc of a full data chunk is better than a series of reallocs */
|
||||||
char *out;
|
char *out;
|
||||||
int out_maxlen = compress ? src_len : (2 * src_len);
|
int out_maxlen = compress ? (src_len + 4) : (2 * src_len);
|
||||||
int limiter = 0;
|
int limiter = 0;
|
||||||
|
|
||||||
/* In practice they never come smaller than this */
|
/* In practice they never come smaller than this */
|
||||||
if (out_maxlen < 21) {
|
if (out_maxlen < 25) {
|
||||||
out_maxlen = 21;
|
out_maxlen = 25;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out_maxlen > payload_limit) {
|
if (out_maxlen > payload_limit) {
|
||||||
@ -172,11 +172,11 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session, int compress,
|
|||||||
if (strm->avail_in) {
|
if (strm->avail_in) {
|
||||||
unsigned long out_ofs = out_maxlen - strm->avail_out;
|
unsigned long out_ofs = out_maxlen - strm->avail_out;
|
||||||
|
|
||||||
out_maxlen += compress ? strm->avail_in : (2 * strm->avail_in);
|
out_maxlen += compress ? (strm->avail_in + 4) : (2 * strm->avail_in);
|
||||||
|
|
||||||
if ((out_maxlen > payload_limit) && !compress && limiter++) {
|
if ((out_maxlen > payload_limit) && !compress && limiter++) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_ZLIB, "Excessive growth in decompression phase", 0);
|
libssh2_error(session, LIBSSH2_ERROR_ZLIB, "Excessive growth in decompression phase", 0);
|
||||||
LIBSSH2_FREE(session, strm->next_out);
|
LIBSSH2_FREE(session, out);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,7 +186,43 @@ static int libssh2_comp_method_zlib_comp(LIBSSH2_SESSION *session, int compress,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
strm->next_out = out + out_ofs;
|
strm->next_out = out + out_ofs;
|
||||||
strm->avail_out += compress ? strm->avail_in : (2 * strm->avail_in);
|
strm->avail_out += compress ? (strm->avail_in + 4) : (2 * strm->avail_in);
|
||||||
|
} else while (!strm->avail_out) {
|
||||||
|
/* Done with input, might be a byte or two in internal buffer during compress
|
||||||
|
* Or potentially many bytes if it's a decompress
|
||||||
|
*/
|
||||||
|
int grow_size = compress ? 8 : 1024;
|
||||||
|
|
||||||
|
if (out_maxlen >= payload_limit) {
|
||||||
|
libssh2_error(session, LIBSSH2_ERROR_ZLIB, "Excessive growth in decompression phase", 0);
|
||||||
|
LIBSSH2_FREE(session, out);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grow_size > (payload_limit - out_maxlen)) {
|
||||||
|
grow_size = payload_limit - out_maxlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_maxlen += grow_size;
|
||||||
|
strm->avail_out = grow_size;
|
||||||
|
|
||||||
|
out = LIBSSH2_REALLOC(session, out, out_maxlen);
|
||||||
|
if (!out) {
|
||||||
|
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to expand final compress/decompress buffer", 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
strm->next_out = out + out_maxlen - grow_size;
|
||||||
|
|
||||||
|
if (compress) {
|
||||||
|
status = deflate(strm, Z_PARTIAL_FLUSH);
|
||||||
|
} else {
|
||||||
|
status = inflate(strm, Z_PARTIAL_FLUSH);
|
||||||
|
}
|
||||||
|
if (status != Z_OK) {
|
||||||
|
libssh2_error(session, LIBSSH2_ERROR_ZLIB, "compress/decompression failure", 0);
|
||||||
|
LIBSSH2_FREE(session, strm->next_out);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user