From 8b7616b47475f37c8f9b89778190d5c82b1db99f Mon Sep 17 00:00:00 2001 From: Tulio Magno Quites Machado Filho Date: Wed, 4 May 2022 12:30:43 -0300 Subject: [PATCH] Enforce ERR_NX_TPBC_GT_SPBC in deflate on more cases After libnxz started to use the history when compressing data, cc = ERR_NX_TPBC_GT_SPBC was not returned all the times it was expected. That happens because the NX considers SPBC to be a sum of the amount of input bytes processed plus the length of the history. Meanwhile, in order to detect ERR_NX_TPBC_GT_SPBC, the length of the history should not be included in SPBC. Fixes issue #161. Signed-off-by: Tulio Magno Quites Machado Filho --- lib/nx_deflate.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lib/nx_deflate.c b/lib/nx_deflate.c index 9ea4f74a..6113605a 100644 --- a/lib/nx_deflate.c +++ b/lib/nx_deflate.c @@ -58,6 +58,11 @@ #include "nx_dbg.h" #include "nx_dht.h" +/** @file nx_deflate.c + * \brief Implement the deflate function for the NX GZIP accelerator and + * related functions. + */ + #define DEF_MEM_LEVEL 8 #define nx_deflateInit(strm, level) nx_deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) @@ -1252,6 +1257,23 @@ static int nx_compress_block(nx_streamp s, int fc, int limit) cc = nx_submit_job(ddl_in, ddl_out, nxcmdp, s->nxdevp); s->nx_cc = cc; + /** The NX GZIP does not subtract the history length from SPBC when + * checking for ERR_NX_TPBC_GT_SPBC. So, there are some scenarios + * where the length of the output is larger than the input, but the + * NX GZIP can't see this. This is particularly critical when the input + * length is < 32KiB. So, we have to check for this scenario and fix + * the result in order to generate better results. + */ + if (!cc) { + uint32_t histlen = getnn(s->nxcmdp->cpb, in_histlen) + * sizeof(nx_qw_t); + uint32_t spbc = get_spbc(s, fc); + uint32_t tpbc = get32(s->nxcmdp->crb.csb, tpbc); + + if (tpbc + histlen > spbc) + cc = ERR_NX_TPBC_GT_SPBC; + } + if (s->dry_run && (cc == ERR_NX_TPBC_GT_SPBC || cc == ERR_NX_OK)) { /* only needed for sampling LZcounts (symbol stats) */ s->dry_run = 0;