From e7b61e1ec3b00947fc8052bccb2906e8d000eff5 Mon Sep 17 00:00:00 2001 From: "josh.macdonald" Date: Fri, 28 Dec 2007 06:09:23 +0000 Subject: Fixes issue 58. Incorrect looping condition in xd3_smatch() caused checking for matches with incorrect checksums, detected by debug builds. This also improves speed slightly and potentially degrades compression where the sprevsz array had spurious matches beyond its actual coverage. --- xdelta3/xdelta3.c | 53 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 20 deletions(-) (limited to 'xdelta3') diff --git a/xdelta3/xdelta3.c b/xdelta3/xdelta3.c index ad8fdb7..b047a3c 100644 --- a/xdelta3/xdelta3.c +++ b/xdelta3/xdelta3.c @@ -4701,12 +4701,12 @@ xd3_smatch (xd3_stream *stream, usize_t scksum, usize_t *match_offset) { - usize_t cmp_len; - usize_t match_length = 0; - usize_t chain = (stream->min_match == MIN_MATCH ? - stream->smatcher.small_chain : - stream->smatcher.small_lchain); - const uint8_t *inp_max = stream->next_in + stream->avail_in; + usize_t cmp_len; + usize_t match_length = 0; + usize_t chain = (stream->min_match == MIN_MATCH ? + stream->smatcher.small_chain : + stream->smatcher.small_lchain); + const uint8_t *inp_max = stream->next_in + stream->avail_in; const uint8_t *inp; const uint8_t *ref; @@ -4718,6 +4718,9 @@ xd3_smatch (xd3_stream *stream, again: + IF_DEBUG1 (DP(RINT "smatch at base=%u inp=%u cksum=%u\n", base, + stream->input_position, scksum)); + /* For small matches, we can always go to the end-of-input because * the matching position must be less than the input position. */ XD3_ASSERT (base < stream->input_position); @@ -4759,24 +4762,34 @@ xd3_smatch (xd3_stream *stream, while (--chain != 0) { /* Calculate the previous offset. */ - usize_t last_pos = stream->small_prev[base & stream->sprevmask].last_pos; + usize_t prev_pos = stream->small_prev[base & stream->sprevmask].last_pos; + usize_t diff_pos; - if (last_pos == 0) - { - break; - } + if (prev_pos == 0) + { + break; + } - last_pos -= HASH_CKOFFSET; - base = last_pos; + prev_pos -= HASH_CKOFFSET; - /* Stop if the position is wrong (because the lists are not - * re-initialized across input windows). */ - if (base < stream->input_position) - { - goto again; - } + if (prev_pos > base) + { + break; + } - break; + base = prev_pos; + + XD3_ASSERT (stream->input_position > base); + diff_pos = stream->input_position - base; + + /* Stop searching if we go beyond sprevsz, since those entries + * are for unrelated checksum entries. */ + if (diff_pos & ~stream->sprevmask) + { + break; + } + + goto again; } done: -- cgit v1.2.3