diff options
-rw-r--r-- | delta.h | 2 | ||||
-rw-r--r-- | diff-delta.c | 8 | ||||
-rw-r--r-- | diffcore-break.c | 2 | ||||
-rw-r--r-- | diffcore-rename.c | 2 | ||||
-rw-r--r-- | mkdelta.c | 3 | ||||
-rw-r--r-- | pack-objects.c | 22 | ||||
-rw-r--r-- | test-delta.c | 6 |
7 files changed, 28 insertions, 17 deletions
@@ -4,7 +4,7 @@ /* handling of delta buffers */ extern void *diff_delta(void *from_buf, unsigned long from_size, void *to_buf, unsigned long to_size, - unsigned long *delta_size); + unsigned long *delta_size, unsigned long max_size); extern void *patch_delta(void *src_buf, unsigned long src_size, void *delta_buf, unsigned long delta_size, unsigned long *dst_size); diff --git a/diff-delta.c b/diff-delta.c index 480f03cd16..fd9b37f491 100644 --- a/diff-delta.c +++ b/diff-delta.c @@ -203,7 +203,8 @@ static void delta_cleanup(bdfile_t *bdf) void *diff_delta(void *from_buf, unsigned long from_size, void *to_buf, unsigned long to_size, - unsigned long *delta_size) + unsigned long *delta_size, + unsigned long max_size) { int i, outpos, outsize, inscnt, csize, msize, moff; unsigned int fp; @@ -312,6 +313,11 @@ void *diff_delta(void *from_buf, unsigned long from_size, } /* next time around the largest possible output is 1 + 4 + 3 */ + if (max_size && outpos > max_size) { + free(out); + delta_cleanup(&bdf); + return NULL; + } if (outpos > outsize - 8) { void *tmp = out; outsize = outsize * 3 / 2; diff --git a/diffcore-break.c b/diffcore-break.c index 920062bfd9..9852f9716c 100644 --- a/diffcore-break.c +++ b/diffcore-break.c @@ -65,7 +65,7 @@ static int should_break(struct diff_filespec *src, delta = diff_delta(src->data, src->size, dst->data, dst->size, - &delta_size); + &delta_size, ~0UL); /* Estimate the edit size by interpreting delta. */ if (count_delta(delta, delta_size, diff --git a/diffcore-rename.c b/diffcore-rename.c index 8fb45f0b87..29609c74b6 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -165,7 +165,7 @@ static int estimate_similarity(struct diff_filespec *src, delta = diff_delta(src->data, src->size, dst->data, dst->size, - &delta_size); + &delta_size, ~0UL); /* A delta that has a lot of literal additions would have * big delta_size no matter what else it does. @@ -278,7 +278,8 @@ int main(int argc, char **argv) continue; } delta_buf = diff_delta(ref[r].buf, ref[r].size, - trg.buf, trg.size, &delta_size); + trg.buf, trg.size, + &delta_size, ~0UL); if (!delta_buf) die("out of memory"); if (trg.depth < max_depth && diff --git a/pack-objects.c b/pack-objects.c index dfa9d44a15..d9328a98d8 100644 --- a/pack-objects.c +++ b/pack-objects.c @@ -83,8 +83,8 @@ static void *delta_against(void *buf, unsigned long size, struct object_entry *e if (!otherbuf) die("unable to read %s", sha1_to_hex(entry->delta->sha1)); - delta_buf = diff_delta(buf, size, otherbuf, othersize, &delta_size); - if (delta_size != entry->delta_size) + delta_buf = diff_delta(buf, size, otherbuf, othersize, &delta_size, ~0UL); + if (!delta_buf || delta_size != entry->delta_size) die("delta size changed"); free(buf); free(otherbuf); @@ -292,6 +292,7 @@ static int try_delta(struct unpacked *cur, struct unpacked *old) struct object_entry *cur_entry = cur->entry; struct object_entry *old_entry = old->entry; unsigned long size, oldsize, delta_size; + long max_size; void *delta_buf; /* Don't bother doing diffs between different types */ @@ -300,6 +301,8 @@ static int try_delta(struct unpacked *cur, struct unpacked *old) /* Size is guaranteed to be larger than or equal to oldsize */ size = cur_entry->size; + if (size < 50) + return -1; oldsize = old_entry->size; if (size - oldsize > oldsize / 4) return -1; @@ -311,15 +314,14 @@ static int try_delta(struct unpacked *cur, struct unpacked *old) * more space-efficient (deletes don't have to say _what_ they * delete). */ - delta_buf = diff_delta(cur->data, size, old->data, oldsize, &delta_size); + max_size = size / 2 - 20; + if (cur_entry->delta) + max_size = cur_entry->delta_size-1; + delta_buf = diff_delta(cur->data, size, old->data, oldsize, &delta_size, max_size); if (!delta_buf) - die("unable to create delta"); - if (delta_size + 20 < size / 2) { - if (!cur_entry->delta || cur_entry->delta_size > delta_size) { - cur_entry->delta = old_entry; - cur_entry->delta_size = delta_size; - } - } + return 0; + cur_entry->delta = old_entry; + cur_entry->delta_size = delta_size; free(delta_buf); return 0; } diff --git a/test-delta.c b/test-delta.c index 8751e27c6b..da51efc245 100644 --- a/test-delta.c +++ b/test-delta.c @@ -60,10 +60,12 @@ int main(int argc, char *argv[]) if (argv[1][1] == 'd') out_buf = diff_delta(from_buf, from_size, - data_buf, data_size, &out_size); + data_buf, data_size, + &out_size, ~0UL); else out_buf = patch_delta(from_buf, from_size, - data_buf, data_size, &out_size); + data_buf, data_size, + &out_size); if (!out_buf) { fprintf(stderr, "delta operation failed (returned NULL)\n"); return 1; |