/* 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);
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;
}
/* 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;
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,
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.
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 &&
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);
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 */
/* 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;
* 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;
}
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;