From 5f338096c1c055587f72ae9d9c93697e1d4dd354 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Sun, 26 Mar 2023 13:16:24 +0100 Subject: [PATCH] [Minor] Fix some issues with the in-place gzip, add gunzip --- src/libutil/util.c | 68 +++++++++++++++++++++++++++++++++++++++++++--- src/libutil/util.h | 10 ++++++- 2 files changed, 73 insertions(+), 5 deletions(-) diff --git a/src/libutil/util.c b/src/libutil/util.c index 539c5070d..253b651ad 100644 --- a/src/libutil/util.c +++ b/src/libutil/util.c @@ -2248,12 +2248,17 @@ rspamd_fstring_gzip (rspamd_fstring_t **in) memset (&strm, 0, sizeof (strm)); ret = deflateInit2 (&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, - MAX_WBITS + 16, MAX_MEM_LEVEL - 1, Z_DEFAULT_STRATEGY); + MAX_WBITS + 16, MAX_MEM_LEVEL - 1, Z_DEFAULT_STRATEGY); if (ret != Z_OK) { return FALSE; } + if (buf->allocated < deflateBound (&strm, buf->len)) { + buf = rspamd_fstring_grow (buf, deflateBound (&strm, buf->len)); + *in = buf; + } + strm.next_in = buf->str; strm.avail_in = buf->len; @@ -2267,16 +2272,17 @@ rspamd_fstring_gzip (rspamd_fstring_t **in) /* Try to compress in-place */ tmp_remain = strm.next_out - temp; if (tmp_remain <= (strm.avail_in ? buf->len - strm.avail_in : buf->allocated)) { - memcpy(buf, temp, tmp_remain); + memcpy(buf->str, temp, tmp_remain); strm.next_out = (unsigned char *)buf->str + tmp_remain; tmp_remain = 0; while (ret == Z_OK) { strm.avail_out = strm.avail_in ? strm.next_in - strm.next_out : - ((unsigned char *)buf->str + buf->allocated) - strm.next_out; + ((unsigned char *)buf->str + buf->allocated) - strm.next_out; ret = deflate(&strm, Z_FINISH); } if (ret != Z_BUF_ERROR || strm.avail_in == 0) { buf->len = strm.next_out - (unsigned char *)buf->str; + *in = buf; return ret == Z_STREAM_END; } } @@ -2289,13 +2295,67 @@ rspamd_fstring_gzip (rspamd_fstring_t **in) memcpy(hold, strm.next_in, strm.avail_in); strm.next_in = hold; if (tmp_remain) { - memcpy(buf, temp, tmp_remain); + memcpy(buf->str, temp, tmp_remain); strm.next_out = (unsigned char *)buf->str + tmp_remain; } strm.avail_out = ((unsigned char *)buf->str + buf->allocated) - strm.next_out; ret = deflate(&strm, Z_FINISH); g_free (hold); buf->len = strm.next_out - (unsigned char *)buf->str; + *in = buf; + + return ret == Z_STREAM_END; +} + +gboolean +rspamd_fstring_gunzip(rspamd_fstring_t **in) +{ + z_stream strm; + rspamd_fstring_t *buf = *in, *out = rspamd_fstring_sized_new ((*in)->len); + int ret; + + memset(&strm, 0, sizeof(strm)); + ret = inflateInit2(&strm, MAX_WBITS + 16); + + if (ret != Z_OK) { + return FALSE; + } + + strm.next_in = buf->str; + strm.avail_in = buf->len; + + gsize total_out = 0; + + do { + strm.next_out = out->str; + strm.avail_out = out->allocated; + + ret = inflate(&strm, Z_NO_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END && ret != Z_BUF_ERROR) { + break; + } + + gsize out_size = out->allocated - strm.avail_out; + if (total_out + out_size > out->allocated) { + out = rspamd_fstring_grow (out, total_out + out_size); + } + + total_out += out_size; + + } while (ret != Z_STREAM_END); + + if (ret == Z_STREAM_END) { + *in = out; + out->len = total_out; + rspamd_fstring_free (buf); + } + else { + /* Revert */ + *in = buf; + rspamd_fstring_free (out); + } + + inflateEnd(&strm); return ret == Z_STREAM_END; } diff --git a/src/libutil/util.h b/src/libutil/util.h index f747bce5b..ccc642adb 100644 --- a/src/libutil/util.h +++ b/src/libutil/util.h @@ -448,12 +448,20 @@ void rspamd_localtime (gint64 ts, struct tm *dest); /** * Compresses the input string using gzip+zlib. Old string is replaced and freed - * if compressed. If not compressed it is untouched. + * if compressed. * @param in * @return TRUE if a string has been compressed */ gboolean rspamd_fstring_gzip (rspamd_fstring_t **in); +/** + * Compresses the input string using gzip+zlib. Old string is replaced and freed + * if compressed. If not compressed it is untouched. + * @param in + * @return TRUE if a string has been compressed + */ +gboolean rspamd_fstring_gunzip (rspamd_fstring_t **in); + /** * Perform globbing searching for the specified path. Allow recursion, * returns an error if maximum nesting is reached. -- 2.39.5