Skip to content

Commit fe474b5

Browse files
Nicolas PitreJunio C Hamano
authored andcommitted
diff-delta: fold two special tests into one plus cleanups
Testing for realloc and size limit can be done with only one test per loop. Make it so and fix a theoretical off-by-one comparison error in the process. The output buffer memory allocation is also bounded by max_size when specified. Finally make some variable unsigned to allow the handling of files up to 4GB in size instead of 2GB. Signed-off-by: Nicolas Pitre <nico@cam.org> Signed-off-by: Junio C Hamano <junkio@cox.net>
1 parent cac251d commit fe474b5

File tree

1 file changed

+14
-10
lines changed

1 file changed

+14
-10
lines changed

diff-delta.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -148,16 +148,20 @@ static void delta_cleanup(bdfile_t *bdf)
148148
cha_free(&bdf->cha);
149149
}
150150

151+
/* provide the size of the copy opcode given the block offset and size */
151152
#define COPYOP_SIZE(o, s) \
152153
(!!(o & 0xff) + !!(o & 0xff00) + !!(o & 0xff0000) + !!(o & 0xff000000) + \
153154
!!(s & 0xff) + !!(s & 0xff00) + 1)
154155

156+
/* the maximum size for any opcode */
157+
#define MAX_OP_SIZE COPYOP_SIZE(0xffffffff, 0xffffffff)
158+
155159
void *diff_delta(void *from_buf, unsigned long from_size,
156160
void *to_buf, unsigned long to_size,
157161
unsigned long *delta_size,
158162
unsigned long max_size)
159163
{
160-
int i, outpos, outsize, inscnt, csize, msize, moff;
164+
unsigned int i, outpos, outsize, inscnt, csize, msize, moff;
161165
unsigned int fp;
162166
const unsigned char *ref_data, *ref_top, *data, *top, *ptr1, *ptr2;
163167
unsigned char *out, *orig;
@@ -169,6 +173,8 @@ void *diff_delta(void *from_buf, unsigned long from_size,
169173

170174
outpos = 0;
171175
outsize = 8192;
176+
if (max_size && outsize >= max_size)
177+
outsize = max_size + MAX_OP_SIZE + 1;
172178
out = malloc(outsize);
173179
if (!out) {
174180
delta_cleanup(&bdf);
@@ -259,17 +265,15 @@ void *diff_delta(void *from_buf, unsigned long from_size,
259265
*orig = i;
260266
}
261267

262-
if (max_size && outpos > max_size) {
263-
free(out);
264-
delta_cleanup(&bdf);
265-
return NULL;
266-
}
267-
268-
/* next time around the largest possible output is 1 + 4 + 3 */
269-
if (outpos > outsize - 8) {
268+
if (outpos >= outsize - MAX_OP_SIZE) {
270269
void *tmp = out;
271270
outsize = outsize * 3 / 2;
272-
out = realloc(out, outsize);
271+
if (max_size && outsize >= max_size)
272+
outsize = max_size + MAX_OP_SIZE + 1;
273+
if (max_size && outpos > max_size)
274+
out = NULL;
275+
else
276+
out = realloc(out, outsize);
273277
if (!out) {
274278
free(tmp);
275279
delta_cleanup(&bdf);

0 commit comments

Comments
 (0)