summaryrefslogtreecommitdiff
path: root/xdelta3
diff options
context:
space:
mode:
authorjosh.macdonald <jmacd@users.noreply.github.com>2007-12-28 06:09:23 +0000
committerjosh.macdonald <jmacd@users.noreply.github.com>2007-12-28 06:09:23 +0000
commite7b61e1ec3b00947fc8052bccb2906e8d000eff5 (patch)
tree47a7237ab3794671320269394304822b09eae140 /xdelta3
parent2e0d675bf995f9f6e893bd41cb4b14304c6c88ab (diff)
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.
Diffstat (limited to 'xdelta3')
-rw-r--r--xdelta3/xdelta3.c53
1 files changed, 33 insertions, 20 deletions
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,
4701 usize_t scksum, 4701 usize_t scksum,
4702 usize_t *match_offset) 4702 usize_t *match_offset)
4703{ 4703{
4704 usize_t cmp_len; 4704 usize_t cmp_len;
4705 usize_t match_length = 0; 4705 usize_t match_length = 0;
4706 usize_t chain = (stream->min_match == MIN_MATCH ? 4706 usize_t chain = (stream->min_match == MIN_MATCH ?
4707 stream->smatcher.small_chain : 4707 stream->smatcher.small_chain :
4708 stream->smatcher.small_lchain); 4708 stream->smatcher.small_lchain);
4709 const uint8_t *inp_max = stream->next_in + stream->avail_in; 4709 const uint8_t *inp_max = stream->next_in + stream->avail_in;
4710 const uint8_t *inp; 4710 const uint8_t *inp;
4711 const uint8_t *ref; 4711 const uint8_t *ref;
4712 4712
@@ -4718,6 +4718,9 @@ xd3_smatch (xd3_stream *stream,
4718 4718
4719 again: 4719 again:
4720 4720
4721 IF_DEBUG1 (DP(RINT "smatch at base=%u inp=%u cksum=%u\n", base,
4722 stream->input_position, scksum));
4723
4721 /* For small matches, we can always go to the end-of-input because 4724 /* For small matches, we can always go to the end-of-input because
4722 * the matching position must be less than the input position. */ 4725 * the matching position must be less than the input position. */
4723 XD3_ASSERT (base < stream->input_position); 4726 XD3_ASSERT (base < stream->input_position);
@@ -4759,24 +4762,34 @@ xd3_smatch (xd3_stream *stream,
4759 while (--chain != 0) 4762 while (--chain != 0)
4760 { 4763 {
4761 /* Calculate the previous offset. */ 4764 /* Calculate the previous offset. */
4762 usize_t last_pos = stream->small_prev[base & stream->sprevmask].last_pos; 4765 usize_t prev_pos = stream->small_prev[base & stream->sprevmask].last_pos;
4766 usize_t diff_pos;
4763 4767
4764 if (last_pos == 0) 4768 if (prev_pos == 0)
4765 { 4769 {
4766 break; 4770 break;
4767 } 4771 }
4768 4772
4769 last_pos -= HASH_CKOFFSET; 4773 prev_pos -= HASH_CKOFFSET;
4770 base = last_pos;
4771 4774
4772 /* Stop if the position is wrong (because the lists are not 4775 if (prev_pos > base)
4773 * re-initialized across input windows). */ 4776 {
4774 if (base < stream->input_position) 4777 break;
4775 { 4778 }
4776 goto again;
4777 }
4778 4779
4779 break; 4780 base = prev_pos;
4781
4782 XD3_ASSERT (stream->input_position > base);
4783 diff_pos = stream->input_position - base;
4784
4785 /* Stop searching if we go beyond sprevsz, since those entries
4786 * are for unrelated checksum entries. */
4787 if (diff_pos & ~stream->sprevmask)
4788 {
4789 break;
4790 }
4791
4792 goto again;
4780 } 4793 }
4781 4794
4782 done: 4795 done: