Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9bc2813

Browse files
author
Vicent Marti
committed
Merge pull request libgit2#2391 from libgit2/rb/clean-up-diff-binary-print
Minor fixes to binary diff code
2 parents 4cf8268 + bc81220 commit 9bc2813

File tree

2 files changed

+55
-38
lines changed

2 files changed

+55
-38
lines changed

src/diff_print.c

Lines changed: 48 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -286,50 +286,46 @@ static int print_binary_hunk(diff_print_info *pi, git_blob *old, git_blob *new)
286286
{
287287
git_buf deflate = GIT_BUF_INIT, delta = GIT_BUF_INIT, *out = NULL;
288288
const void *old_data, *new_data;
289-
git_off_t off_t_old_data_len, off_t_new_data_len;
290-
unsigned long old_data_len, new_data_len, delta_data_len, inflated_len;
291-
size_t remain;
289+
git_off_t old_data_len, new_data_len;
290+
unsigned long delta_data_len, inflated_len;
292291
const char *out_type = "literal";
293-
char *ptr;
292+
char *scan, *end;
294293
int error;
295294

296295
old_data = old ? git_blob_rawcontent(old) : NULL;
297296
new_data = new ? git_blob_rawcontent(new) : NULL;
298297

299-
off_t_old_data_len = old ? git_blob_rawsize(old) : 0;
300-
off_t_new_data_len = new ? git_blob_rawsize(new) : 0;
298+
old_data_len = old ? git_blob_rawsize(old) : 0;
299+
new_data_len = new ? git_blob_rawsize(new) : 0;
301300

302301
/* The git_delta function accepts unsigned long only */
303-
if (off_t_old_data_len > ULONG_MAX || off_t_new_data_len > ULONG_MAX) {
304-
error = -1;
305-
goto done;
306-
}
307-
308-
old_data_len = (unsigned long)off_t_old_data_len;
309-
new_data_len = (unsigned long)off_t_new_data_len;
302+
if (!git__is_ulong(old_data_len) || !git__is_ulong(new_data_len))
303+
return GIT_EBUFS;
310304

311305
out = &deflate;
312-
inflated_len = new_data_len;
306+
inflated_len = (unsigned long)new_data_len;
313307

314308
if ((error = git_zstream_deflatebuf(
315-
&deflate, new_data, new_data_len)) < 0)
309+
out, new_data, (size_t)new_data_len)) < 0)
316310
goto done;
317311

318312
/* The git_delta function accepts unsigned long only */
319-
if (deflate.size > ULONG_MAX) {
320-
error = -1;
313+
if (!git__is_ulong((git_off_t)deflate.size)) {
314+
error = GIT_EBUFS;
321315
goto done;
322316
}
323317

324318
if (old && new) {
325-
void *delta_data;
326-
327-
delta_data = git_delta(old_data, old_data_len, new_data,
328-
new_data_len, &delta_data_len, (unsigned long)deflate.size);
319+
void *delta_data = git_delta(
320+
old_data, (unsigned long)old_data_len,
321+
new_data, (unsigned long)new_data_len,
322+
&delta_data_len, (unsigned long)deflate.size);
329323

330324
if (delta_data) {
331-
error = git_zstream_deflatebuf(&delta, delta_data, delta_data_len);
332-
free(delta_data);
325+
error = git_zstream_deflatebuf(
326+
&delta, delta_data, (size_t)delta_data_len);
327+
328+
git__free(delta_data);
333329

334330
if (error < 0)
335331
goto done;
@@ -345,24 +341,25 @@ static int print_binary_hunk(diff_print_info *pi, git_blob *old, git_blob *new)
345341
git_buf_printf(pi->buf, "%s %lu\n", out_type, inflated_len);
346342
pi->line.num_lines++;
347343

348-
for (ptr = out->ptr, remain = out->size; remain > 0; ) {
349-
size_t chunk_len = (52 < remain) ? 52 : remain;
344+
for (scan = out->ptr, end = out->ptr + out->size; scan < end; ) {
345+
size_t chunk_len = end - scan;
346+
if (chunk_len > 52)
347+
chunk_len = 52;
350348

351349
if (chunk_len <= 26)
352350
git_buf_putc(pi->buf, (char)chunk_len + 'A' - 1);
353351
else
354352
git_buf_putc(pi->buf, (char)chunk_len - 26 + 'a' - 1);
355353

356-
git_buf_put_base85(pi->buf, ptr, chunk_len);
354+
git_buf_put_base85(pi->buf, scan, chunk_len);
357355
git_buf_putc(pi->buf, '\n');
358356

359357
if (git_buf_oom(pi->buf)) {
360358
error = -1;
361359
goto done;
362360
}
363361

364-
ptr += chunk_len;
365-
remain -= chunk_len;
362+
scan += chunk_len;
366363
pi->line.num_lines++;
367364
}
368365

@@ -381,26 +378,33 @@ static int diff_print_patch_file_binary(
381378
git_blob *old = NULL, *new = NULL;
382379
const git_oid *old_id, *new_id;
383380
int error;
381+
size_t pre_binary_size;
384382

385-
if ((pi->flags & GIT_DIFF_SHOW_BINARY) == 0) {
386-
pi->line.num_lines = 1;
387-
return diff_delta_format_with_paths(
388-
pi->buf, delta, oldpfx, newpfx,
389-
"Binary files %s%s and %s%s differ\n");
390-
}
383+
if ((pi->flags & GIT_DIFF_SHOW_BINARY) == 0)
384+
goto noshow;
391385

386+
pre_binary_size = pi->buf->size;
392387
git_buf_printf(pi->buf, "GIT binary patch\n");
393388
pi->line.num_lines++;
394389

395390
old_id = (delta->status != GIT_DELTA_ADDED) ? &delta->old_file.id : NULL;
396391
new_id = (delta->status != GIT_DELTA_DELETED) ? &delta->new_file.id : NULL;
397392

398-
if ((old_id && (error = git_blob_lookup(&old, pi->diff->repo, old_id)) < 0) ||
399-
(new_id && (error = git_blob_lookup(&new, pi->diff->repo,new_id)) < 0) ||
400-
(error = print_binary_hunk(pi, old, new)) < 0 ||
393+
if (old_id && (error = git_blob_lookup(&old, pi->diff->repo, old_id)) < 0)
394+
goto done;
395+
if (new_id && (error = git_blob_lookup(&new, pi->diff->repo,new_id)) < 0)
396+
goto done;
397+
398+
if ((error = print_binary_hunk(pi, old, new)) < 0 ||
401399
(error = git_buf_putc(pi->buf, '\n')) < 0 ||
402400
(error = print_binary_hunk(pi, new, old)) < 0)
403-
goto done;
401+
{
402+
if (error == GIT_EBUFS) {
403+
giterr_clear();
404+
git_buf_truncate(pi->buf, pre_binary_size);
405+
goto noshow;
406+
}
407+
}
404408

405409
pi->line.num_lines++;
406410

@@ -409,6 +413,12 @@ static int diff_print_patch_file_binary(
409413
git_blob_free(new);
410414

411415
return error;
416+
417+
noshow:
418+
pi->line.num_lines = 1;
419+
return diff_delta_format_with_paths(
420+
pi->buf, delta, oldpfx, newpfx,
421+
"Binary files %s%s and %s%s differ\n");
412422
}
413423

414424
static int diff_print_patch_file(

src/util.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,13 @@ GIT_INLINE(int) git__is_uint32(size_t p)
133133
return p == (size_t)r;
134134
}
135135

136+
/** @return true if p fits into the range of an unsigned long */
137+
GIT_INLINE(int) git__is_ulong(git_off_t p)
138+
{
139+
unsigned long r = (unsigned long)p;
140+
return p == (git_off_t)r;
141+
}
142+
136143
/* 32-bit cross-platform rotl */
137144
#ifdef _MSC_VER /* use built-in method in MSVC */
138145
# define git__rotl(v, s) (uint32_t)_rotl(v, s)

0 commit comments

Comments
 (0)