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

Skip to content

Commit ac69a82

Browse files
committed
Merge pull request libgit2#3451 from ethomson/xdiff
xdiff fixes
2 parents a99f33e + ae195a7 commit ac69a82

16 files changed

+335
-155
lines changed

src/blame.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ static int blame_internal(git_blame *blame)
331331

332332
blame->ent = ent;
333333

334-
git_blame__like_git(blame, blame->options.flags);
334+
error = git_blame__like_git(blame, blame->options.flags);
335335

336336
cleanup:
337337
for (ent = blame->ent; ent; ) {

src/blame_git.c

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "commit.h"
1010
#include "blob.h"
1111
#include "xdiff/xinclude.h"
12+
#include "diff_xdiff.h"
1213

1314
/*
1415
* Origin is refcounted and usually we keep the blob contents to be
@@ -351,6 +352,13 @@ static int diff_hunks(mmfile_t file_a, mmfile_t file_b, void *cb_data)
351352
ecb.priv = cb_data;
352353

353354
trim_common_tail(&file_a, &file_b, 0);
355+
356+
if (file_a.size > GIT_XDIFF_MAX_SIZE ||
357+
file_b.size > GIT_XDIFF_MAX_SIZE) {
358+
giterr_set(GITERR_INVALID, "file too large to blame");
359+
return -1;
360+
}
361+
354362
return xdl_diff(&file_a, &file_b, &xpp, &xecfg, &ecb);
355363
}
356364

@@ -379,7 +387,9 @@ static int pass_blame_to_parent(
379387
fill_origin_blob(parent, &file_p);
380388
fill_origin_blob(target, &file_o);
381389

382-
diff_hunks(file_p, file_o, &d);
390+
if (diff_hunks(file_p, file_o, &d) < 0)
391+
return -1;
392+
383393
/* The reset (i.e. anything after tlno) are the same as the parent */
384394
blame_chunk(blame, d.tlno, d.plno, last_in_target, target, parent);
385395

@@ -477,12 +487,13 @@ static void pass_whole_blame(git_blame *blame,
477487
}
478488
}
479489

480-
static void pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt)
490+
static int pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt)
481491
{
482492
git_commit *commit = origin->commit;
483493
int i, num_parents;
484494
git_blame__origin *sg_buf[16];
485495
git_blame__origin *porigin, **sg_origin = sg_buf;
496+
int ret, error = 0;
486497

487498
num_parents = git_commit_parentcount(commit);
488499
if (!git_oid_cmp(git_commit_id(commit), &blame->options.oldest_commit))
@@ -540,8 +551,13 @@ static void pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt
540551
origin_incref(porigin);
541552
origin->previous = porigin;
542553
}
543-
if (pass_blame_to_parent(blame, origin, porigin))
554+
555+
if ((ret = pass_blame_to_parent(blame, origin, porigin)) != 0) {
556+
if (ret < 0)
557+
error = -1;
558+
544559
goto finish;
560+
}
545561
}
546562

547563
/* TODO: optionally find moves in parents' files */
@@ -554,7 +570,7 @@ static void pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt
554570
origin_decref(sg_origin[i]);
555571
if (sg_origin != sg_buf)
556572
git__free(sg_origin);
557-
return;
573+
return error;
558574
}
559575

560576
/*
@@ -583,7 +599,7 @@ static void coalesce(git_blame *blame)
583599
}
584600
}
585601

586-
void git_blame__like_git(git_blame *blame, uint32_t opt)
602+
int git_blame__like_git(git_blame *blame, uint32_t opt)
587603
{
588604
while (true) {
589605
git_blame__entry *ent;
@@ -594,11 +610,13 @@ void git_blame__like_git(git_blame *blame, uint32_t opt)
594610
if (!ent->guilty)
595611
suspect = ent->suspect;
596612
if (!suspect)
597-
return; /* all done */
613+
return 0; /* all done */
598614

599615
/* We'll use this suspect later in the loop, so hold on to it for now. */
600616
origin_incref(suspect);
601-
pass_blame(blame, suspect, opt);
617+
618+
if (pass_blame(blame, suspect, opt) < 0)
619+
return -1;
602620

603621
/* Take responsibility for the remaining entries */
604622
for (ent = blame->ent; ent; ent = ent->next) {
@@ -613,6 +631,8 @@ void git_blame__like_git(git_blame *blame, uint32_t opt)
613631
}
614632

615633
coalesce(blame);
634+
635+
return 0;
616636
}
617637

618638
void git_blame__free_entry(git_blame__entry *ent)

src/blame_git.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ int git_blame__get_origin(
1515
git_commit *commit,
1616
const char *path);
1717
void git_blame__free_entry(git_blame__entry *ent);
18-
void git_blame__like_git(git_blame *sb, uint32_t flags);
18+
int git_blame__like_git(git_blame *sb, uint32_t flags);
1919

2020
#endif

src/checkout.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "git2/submodule.h"
1919
#include "git2/sys/index.h"
2020
#include "git2/sys/filter.h"
21+
#include "git2/merge.h"
2122

2223
#include "refs.h"
2324
#include "repository.h"
@@ -27,7 +28,7 @@
2728
#include "diff.h"
2829
#include "pathspec.h"
2930
#include "buf_text.h"
30-
#include "merge_file.h"
31+
#include "diff_xdiff.h"
3132
#include "path.h"
3233
#include "attr.h"
3334
#include "pool.h"

src/common.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,15 @@ GIT_INLINE(void) git__init_structure(void *structure, size_t len, unsigned int v
208208
#define GITERR_CHECK_ALLOC_ADD(out, one, two) \
209209
if (GIT_ADD_SIZET_OVERFLOW(out, one, two)) { return -1; }
210210

211+
#define GITERR_CHECK_ALLOC_ADD3(out, one, two, three) \
212+
if (GIT_ADD_SIZET_OVERFLOW(out, one, two) || \
213+
GIT_ADD_SIZET_OVERFLOW(out, *(out), three)) { return -1; }
214+
215+
#define GITERR_CHECK_ALLOC_ADD4(out, one, two, three, four) \
216+
if (GIT_ADD_SIZET_OVERFLOW(out, one, two) || \
217+
GIT_ADD_SIZET_OVERFLOW(out, *(out), three) || \
218+
GIT_ADD_SIZET_OVERFLOW(out, *(out), four)) { return -1; }
219+
211220
/** Check for multiplicative overflow, failing if it would occur. */
212221
#define GITERR_CHECK_ALLOC_MULTIPLY(out, nelem, elsize) \
213222
if (GIT_MULTIPLY_SIZET_OVERFLOW(out, nelem, elsize)) { return -1; }

src/diff_patch.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ static void diff_patch_update_binary(git_patch *patch)
3030
(patch->nfile.file->flags & GIT_DIFF_FLAG_BINARY) != 0)
3131
patch->delta->flags |= GIT_DIFF_FLAG_BINARY;
3232

33+
else if (patch->ofile.file->size > GIT_XDIFF_MAX_SIZE ||
34+
patch->nfile.file->size > GIT_XDIFF_MAX_SIZE)
35+
patch->delta->flags |= GIT_DIFF_FLAG_BINARY;
36+
3337
else if ((patch->ofile.file->flags & DIFF_FLAGS_NOT_BINARY) != 0 &&
3438
(patch->nfile.file->flags & DIFF_FLAGS_NOT_BINARY) != 0)
3539
patch->delta->flags |= GIT_DIFF_FLAG_NOT_BINARY;

src/diff_xdiff.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* This file is part of libgit2, distributed under the GNU GPL v2 with
55
* a Linking Exception. For full terms see the included COPYING file.
66
*/
7+
#include "git2/errors.h"
78
#include "common.h"
89
#include "diff.h"
910
#include "diff_driver.h"
@@ -208,6 +209,12 @@ static int git_xdiff(git_diff_output *output, git_patch *patch)
208209
git_patch__old_data(&info.xd_old_data.ptr, &info.xd_old_data.size, patch);
209210
git_patch__new_data(&info.xd_new_data.ptr, &info.xd_new_data.size, patch);
210211

212+
if (info.xd_old_data.size > GIT_XDIFF_MAX_SIZE ||
213+
info.xd_new_data.size > GIT_XDIFF_MAX_SIZE) {
214+
giterr_set(GITERR_INVALID, "files too large for diff");
215+
return -1;
216+
}
217+
211218
xdl_diff(&info.xd_old_data, &info.xd_new_data,
212219
&xo->params, &xo->config, &xo->callback);
213220

src/diff_xdiff.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
#include "diff_patch.h"
1212
#include "xdiff/xdiff.h"
1313

14+
/* xdiff cannot cope with large files. these files should not be passed to
15+
* xdiff. callers should treat these large files as binary.
16+
*/
17+
#define GIT_XDIFF_MAX_SIZE (1024LL * 1024 * 1023)
18+
1419
/* A git_xdiff_output is a git_diff_output with extra fields necessary
1520
* to use libxdiff. Calling git_xdiff_init() will set the diff_cb field
1621
* of the output to use xdiff to generate the diffs.

src/merge.c

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
#include "diff.h"
2121
#include "checkout.h"
2222
#include "tree.h"
23-
#include "merge_file.h"
2423
#include "blob.h"
2524
#include "oid.h"
2625
#include "index.h"
@@ -61,12 +60,6 @@ struct merge_diff_df_data {
6160
git_merge_diff *prev_conflict;
6261
};
6362

64-
GIT_INLINE(int) merge_diff_detect_binary(
65-
bool *binary_out,
66-
git_repository *repo,
67-
const git_merge_diff *conflict);
68-
69-
7063
/* Merge base computation */
7164

7265
int merge_bases_many(git_commit_list **out, git_revwalk **walk_out, git_repository *repo, size_t length, const git_oid input_array[])
@@ -668,7 +661,6 @@ static int merge_conflict_resolve_automerge(
668661
git_odb *odb = NULL;
669662
git_oid automerge_oid;
670663
int error = 0;
671-
bool binary = false;
672664

673665
assert(resolved && diff_list && conflict);
674666

@@ -703,12 +695,6 @@ static int merge_conflict_resolve_automerge(
703695
strcmp(conflict->ancestor_entry.path, conflict->their_entry.path) != 0)
704696
return 0;
705697

706-
/* Reject binary conflicts */
707-
if ((error = merge_diff_detect_binary(&binary, diff_list->repo, conflict)) < 0)
708-
return error;
709-
if (binary)
710-
return 0;
711-
712698
ancestor = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry) ?
713699
&conflict->ancestor_entry : NULL;
714700
ours = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ?
@@ -1314,48 +1300,6 @@ GIT_INLINE(int) merge_diff_detect_type(
13141300
return 0;
13151301
}
13161302

1317-
GIT_INLINE(int) merge_diff_detect_binary(
1318-
bool *binary_out,
1319-
git_repository *repo,
1320-
const git_merge_diff *conflict)
1321-
{
1322-
git_blob *ancestor_blob = NULL, *our_blob = NULL, *their_blob = NULL;
1323-
int error = 0;
1324-
bool binary = false;
1325-
1326-
if (GIT_MERGE_INDEX_ENTRY_ISFILE(conflict->ancestor_entry)) {
1327-
if ((error = git_blob_lookup(&ancestor_blob, repo, &conflict->ancestor_entry.id)) < 0)
1328-
goto done;
1329-
1330-
binary = git_blob_is_binary(ancestor_blob);
1331-
}
1332-
1333-
if (!binary &&
1334-
GIT_MERGE_INDEX_ENTRY_ISFILE(conflict->our_entry)) {
1335-
if ((error = git_blob_lookup(&our_blob, repo, &conflict->our_entry.id)) < 0)
1336-
goto done;
1337-
1338-
binary = git_blob_is_binary(our_blob);
1339-
}
1340-
1341-
if (!binary &&
1342-
GIT_MERGE_INDEX_ENTRY_ISFILE(conflict->their_entry)) {
1343-
if ((error = git_blob_lookup(&their_blob, repo, &conflict->their_entry.id)) < 0)
1344-
goto done;
1345-
1346-
binary = git_blob_is_binary(their_blob);
1347-
}
1348-
1349-
*binary_out = binary;
1350-
1351-
done:
1352-
git_blob_free(ancestor_blob);
1353-
git_blob_free(our_blob);
1354-
git_blob_free(their_blob);
1355-
1356-
return error;
1357-
}
1358-
13591303
GIT_INLINE(int) index_entry_dup_pool(
13601304
git_index_entry *out,
13611305
git_pool *pool,

0 commit comments

Comments
 (0)