From: Gao Xiang Date: Fri, 9 Aug 2024 10:56:36 +0000 (+0800) Subject: erofs-utils: fuse: fix partial decompression for libdeflate X-Git-Tag: v1.8.1~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8895abbc282edd5ea795f971b43b0a601a0b443d;p=platform%2Fupstream%2Ferofs-utils.git erofs-utils: fuse: fix partial decompression for libdeflate Actually, libdeflate doesn't support partial decompression; therefore, fix it by reallocating larger decompression buffers. Although a better approach would be to obtain the exact decompressed length instead for libdeflate decompressor, which requires more changes, a quick fix is needed. Fixes: 29b9e7140162 ("erofs-utils: fuse,fsck: add DEFLATE algorithm support") Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20240809105636.3641536-1-hsiangkao@linux.alibaba.com --- diff --git a/lib/decompress.c b/lib/decompress.c index 1b44a18..3f553a8 100644 --- a/lib/decompress.c +++ b/lib/decompress.c @@ -247,32 +247,47 @@ static int z_erofs_decompress_deflate(struct z_erofs_decompress_req *rq) unsigned int inputmargin; struct libdeflate_decompressor *inf; enum libdeflate_result ret; + unsigned int decodedcapacity; inputmargin = z_erofs_fixup_insize(src, rq->inputsize); if (inputmargin >= rq->inputsize) return -EFSCORRUPTED; - if (rq->decodedskip) { - buff = malloc(rq->decodedlength); + decodedcapacity = rq->decodedlength << (4 * rq->partial_decoding); + if (rq->decodedskip || rq->partial_decoding) { + buff = malloc(decodedcapacity); if (!buff) return -ENOMEM; dest = buff; } inf = libdeflate_alloc_decompressor(); - if (!inf) - return -ENOMEM; + if (!inf) { + ret = -ENOMEM; + goto out_free_mem; + } if (rq->partial_decoding) { - ret = libdeflate_deflate_decompress(inf, src + inputmargin, - rq->inputsize - inputmargin, dest, - rq->decodedlength, &actual_out); - if (ret && ret != LIBDEFLATE_INSUFFICIENT_SPACE) { - ret = -EIO; - goto out_inflate_end; + while (1) { + ret = libdeflate_deflate_decompress(inf, src + inputmargin, + rq->inputsize - inputmargin, dest, + decodedcapacity, &actual_out); + if (ret == LIBDEFLATE_SUCCESS) + break; + if (ret != LIBDEFLATE_INSUFFICIENT_SPACE) { + ret = -EIO; + goto out_inflate_end; + } + decodedcapacity = decodedcapacity << 1; + dest = realloc(buff, decodedcapacity); + if (!dest) { + ret = -ENOMEM; + goto out_inflate_end; + } + buff = dest; } - if (actual_out != rq->decodedlength) { + if (actual_out < rq->decodedlength) { ret = -EIO; goto out_inflate_end; } @@ -280,18 +295,19 @@ static int z_erofs_decompress_deflate(struct z_erofs_decompress_req *rq) ret = libdeflate_deflate_decompress(inf, src + inputmargin, rq->inputsize - inputmargin, dest, rq->decodedlength, NULL); - if (ret) { + if (ret != LIBDEFLATE_SUCCESS) { ret = -EIO; goto out_inflate_end; } } - if (rq->decodedskip) + if (rq->decodedskip || rq->partial_decoding) memcpy(rq->out, dest + rq->decodedskip, rq->decodedlength - rq->decodedskip); out_inflate_end: libdeflate_free_decompressor(inf); +out_free_mem: if (buff) free(buff); return ret;