mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-08 15:24:11 +00:00
blame: guard xdiff calls for large files
This commit is contained in:
parent
6c014bcc54
commit
ae195a71ae
@ -331,7 +331,7 @@ static int blame_internal(git_blame *blame)
|
|||||||
|
|
||||||
blame->ent = ent;
|
blame->ent = ent;
|
||||||
|
|
||||||
git_blame__like_git(blame, blame->options.flags);
|
error = git_blame__like_git(blame, blame->options.flags);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
for (ent = blame->ent; ent; ) {
|
for (ent = blame->ent; ent; ) {
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "commit.h"
|
#include "commit.h"
|
||||||
#include "blob.h"
|
#include "blob.h"
|
||||||
#include "xdiff/xinclude.h"
|
#include "xdiff/xinclude.h"
|
||||||
|
#include "diff_xdiff.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Origin is refcounted and usually we keep the blob contents to be
|
* 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)
|
|||||||
ecb.priv = cb_data;
|
ecb.priv = cb_data;
|
||||||
|
|
||||||
trim_common_tail(&file_a, &file_b, 0);
|
trim_common_tail(&file_a, &file_b, 0);
|
||||||
|
|
||||||
|
if (file_a.size > GIT_XDIFF_MAX_SIZE ||
|
||||||
|
file_b.size > GIT_XDIFF_MAX_SIZE) {
|
||||||
|
giterr_set(GITERR_INVALID, "file too large to blame");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return xdl_diff(&file_a, &file_b, &xpp, &xecfg, &ecb);
|
return xdl_diff(&file_a, &file_b, &xpp, &xecfg, &ecb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,7 +387,9 @@ static int pass_blame_to_parent(
|
|||||||
fill_origin_blob(parent, &file_p);
|
fill_origin_blob(parent, &file_p);
|
||||||
fill_origin_blob(target, &file_o);
|
fill_origin_blob(target, &file_o);
|
||||||
|
|
||||||
diff_hunks(file_p, file_o, &d);
|
if (diff_hunks(file_p, file_o, &d) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
/* The reset (i.e. anything after tlno) are the same as the parent */
|
/* The reset (i.e. anything after tlno) are the same as the parent */
|
||||||
blame_chunk(blame, d.tlno, d.plno, last_in_target, target, parent);
|
blame_chunk(blame, d.tlno, d.plno, last_in_target, target, parent);
|
||||||
|
|
||||||
@ -477,12 +487,13 @@ static void pass_whole_blame(git_blame *blame,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt)
|
static int pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt)
|
||||||
{
|
{
|
||||||
git_commit *commit = origin->commit;
|
git_commit *commit = origin->commit;
|
||||||
int i, num_parents;
|
int i, num_parents;
|
||||||
git_blame__origin *sg_buf[16];
|
git_blame__origin *sg_buf[16];
|
||||||
git_blame__origin *porigin, **sg_origin = sg_buf;
|
git_blame__origin *porigin, **sg_origin = sg_buf;
|
||||||
|
int ret, error = 0;
|
||||||
|
|
||||||
num_parents = git_commit_parentcount(commit);
|
num_parents = git_commit_parentcount(commit);
|
||||||
if (!git_oid_cmp(git_commit_id(commit), &blame->options.oldest_commit))
|
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
|
|||||||
origin_incref(porigin);
|
origin_incref(porigin);
|
||||||
origin->previous = porigin;
|
origin->previous = porigin;
|
||||||
}
|
}
|
||||||
if (pass_blame_to_parent(blame, origin, porigin))
|
|
||||||
|
if ((ret = pass_blame_to_parent(blame, origin, porigin)) != 0) {
|
||||||
|
if (ret < 0)
|
||||||
|
error = -1;
|
||||||
|
|
||||||
goto finish;
|
goto finish;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: optionally find moves in parents' files */
|
/* TODO: optionally find moves in parents' files */
|
||||||
@ -554,7 +570,7 @@ finish:
|
|||||||
origin_decref(sg_origin[i]);
|
origin_decref(sg_origin[i]);
|
||||||
if (sg_origin != sg_buf)
|
if (sg_origin != sg_buf)
|
||||||
git__free(sg_origin);
|
git__free(sg_origin);
|
||||||
return;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -583,7 +599,7 @@ static void coalesce(git_blame *blame)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_blame__like_git(git_blame *blame, uint32_t opt)
|
int git_blame__like_git(git_blame *blame, uint32_t opt)
|
||||||
{
|
{
|
||||||
while (true) {
|
while (true) {
|
||||||
git_blame__entry *ent;
|
git_blame__entry *ent;
|
||||||
@ -594,11 +610,13 @@ void git_blame__like_git(git_blame *blame, uint32_t opt)
|
|||||||
if (!ent->guilty)
|
if (!ent->guilty)
|
||||||
suspect = ent->suspect;
|
suspect = ent->suspect;
|
||||||
if (!suspect)
|
if (!suspect)
|
||||||
return; /* all done */
|
return 0; /* all done */
|
||||||
|
|
||||||
/* We'll use this suspect later in the loop, so hold on to it for now. */
|
/* We'll use this suspect later in the loop, so hold on to it for now. */
|
||||||
origin_incref(suspect);
|
origin_incref(suspect);
|
||||||
pass_blame(blame, suspect, opt);
|
|
||||||
|
if (pass_blame(blame, suspect, opt) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
/* Take responsibility for the remaining entries */
|
/* Take responsibility for the remaining entries */
|
||||||
for (ent = blame->ent; ent; ent = ent->next) {
|
for (ent = blame->ent; ent; ent = ent->next) {
|
||||||
@ -613,6 +631,8 @@ void git_blame__like_git(git_blame *blame, uint32_t opt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
coalesce(blame);
|
coalesce(blame);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_blame__free_entry(git_blame__entry *ent)
|
void git_blame__free_entry(git_blame__entry *ent)
|
||||||
|
@ -15,6 +15,6 @@ int git_blame__get_origin(
|
|||||||
git_commit *commit,
|
git_commit *commit,
|
||||||
const char *path);
|
const char *path);
|
||||||
void git_blame__free_entry(git_blame__entry *ent);
|
void git_blame__free_entry(git_blame__entry *ent);
|
||||||
void git_blame__like_git(git_blame *sb, uint32_t flags);
|
int git_blame__like_git(git_blame *sb, uint32_t flags);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user