From dbc624d7663c4e159ab4c1f3eddd642b1c28014e Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sat, 13 Apr 2019 23:21:42 -0700 Subject: [PATCH] lcpit_matchfinder: fix limiting nice_match_len The "normal" mode of the lcp-interval tree matchfinder supports finding matches up to LCP_MAX bytes. The "huge" mode, which is needed on buffers larger than 64 MiB, supports up to HUGE_LCP_MAX bytes. nice_match_len must be limited to the appropriate one of these values. But nice_match_len is limited by lcpit_matchfinder_init(). That's wrong, because it only knows whether huge mode *might* be used later, based on max_bufsize. Which mode to use is actually decided on a buffer-by-buffer basis by lcpit_matchfinder_load_buffer(). Thus, limit nice_match_len in lcpit_matchfinder_load_buffer() instead. This fixes a crash or incorrect output during LZMS compression with a compression level > 50 and a chunk size > 64 MiB. --- include/wimlib/lcpit_matchfinder.h | 1 + src/lcpit_matchfinder.c | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/wimlib/lcpit_matchfinder.h b/include/wimlib/lcpit_matchfinder.h index 662eae11..6391a481 100644 --- a/include/wimlib/lcpit_matchfinder.h +++ b/include/wimlib/lcpit_matchfinder.h @@ -37,6 +37,7 @@ struct lcpit_matchfinder { u32 min_match_len; u32 nice_match_len; u32 next[2]; + u32 orig_nice_match_len; }; struct lz_match { diff --git a/src/lcpit_matchfinder.c b/src/lcpit_matchfinder.c index a2d6a1e0..b5a14e93 100644 --- a/src/lcpit_matchfinder.c +++ b/src/lcpit_matchfinder.c @@ -593,9 +593,7 @@ lcpit_matchfinder_init(struct lcpit_matchfinder *mf, size_t max_bufsize, } mf->min_match_len = min_match_len; - mf->nice_match_len = min(nice_match_len, - (max_bufsize <= MAX_NORMAL_BUFSIZE) ? - LCP_MAX : HUGE_LCP_MAX); + mf->orig_nice_match_len = nice_match_len; return true; } @@ -664,6 +662,7 @@ lcpit_matchfinder_load_buffer(struct lcpit_matchfinder *mf, const u8 *T, u32 n) build_SA(mf->intervals, T, n, mf->pos_data); build_ISA(mf->pos_data, mf->intervals, n); if (n <= MAX_NORMAL_BUFSIZE) { + mf->nice_match_len = min(mf->orig_nice_match_len, LCP_MAX); for (u32 i = 0; i < PREFETCH_SAFETY; i++) { mf->intervals[n + i] = 0; mf->pos_data[n + i] = 0; @@ -673,6 +672,7 @@ lcpit_matchfinder_load_buffer(struct lcpit_matchfinder *mf, const u8 *T, u32 n) build_LCPIT(mf->intervals, mf->pos_data, n); mf->huge_mode = false; } else { + mf->nice_match_len = min(mf->orig_nice_match_len, HUGE_LCP_MAX); for (u32 i = 0; i < PREFETCH_SAFETY; i++) { mf->intervals64[n + i] = 0; mf->pos_data[n + i] = 0; -- 2.43.0