Skip to content

Commit 6cc14ae

Browse files
authored
Merge pull request libgit2#4840 from libgit2/cmn/validity-tree-from-unowned-index
Check object existence when creating a tree from an index
2 parents a2f9f94 + c79e608 commit 6cc14ae

File tree

5 files changed

+58
-29
lines changed

5 files changed

+58
-29
lines changed

src/tree.c

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,36 @@ static size_t find_next_dir(const char *dirname, git_index *index, size_t start)
456456
return i;
457457
}
458458

459+
static git_otype otype_from_mode(git_filemode_t filemode)
460+
{
461+
switch (filemode) {
462+
case GIT_FILEMODE_TREE:
463+
return GIT_OBJ_TREE;
464+
case GIT_FILEMODE_COMMIT:
465+
return GIT_OBJ_COMMIT;
466+
default:
467+
return GIT_OBJ_BLOB;
468+
}
469+
}
470+
471+
static int check_entry(git_repository *repo, const char *filename, const git_oid *id, git_filemode_t filemode)
472+
{
473+
if (!valid_filemode(filemode))
474+
return tree_error("failed to insert entry: invalid filemode for file", filename);
475+
476+
if (!valid_entry_name(repo, filename))
477+
return tree_error("failed to insert entry: invalid name for a tree entry", filename);
478+
479+
if (git_oid_iszero(id))
480+
return tree_error("failed to insert entry: invalid null OID", filename);
481+
482+
if (filemode != GIT_FILEMODE_COMMIT &&
483+
!git_object__is_valid(repo, id, otype_from_mode(filemode)))
484+
return tree_error("failed to insert entry: invalid object specified", filename);
485+
486+
return 0;
487+
}
488+
459489
static int append_entry(
460490
git_treebuilder *bld,
461491
const char *filename,
@@ -466,11 +496,8 @@ static int append_entry(
466496
git_tree_entry *entry;
467497
int error = 0;
468498

469-
if (validate && !valid_entry_name(bld->repo, filename))
470-
return tree_error("failed to insert entry: invalid name for a tree entry", filename);
471-
472-
if (validate && git_oid_iszero(id))
473-
return tree_error("failed to insert entry: invalid null OID for a tree entry", filename);
499+
if (validate && ((error = check_entry(bld->repo, filename, id, filemode)) < 0))
500+
return error;
474501

475502
entry = alloc_entry(filename, strlen(filename), id);
476503
GITERR_CHECK_ALLOC(entry);
@@ -684,18 +711,6 @@ int git_treebuilder_new(
684711
return -1;
685712
}
686713

687-
static git_otype otype_from_mode(git_filemode_t filemode)
688-
{
689-
switch (filemode) {
690-
case GIT_FILEMODE_TREE:
691-
return GIT_OBJ_TREE;
692-
case GIT_FILEMODE_COMMIT:
693-
return GIT_OBJ_COMMIT;
694-
default:
695-
return GIT_OBJ_BLOB;
696-
}
697-
}
698-
699714
int git_treebuilder_insert(
700715
const git_tree_entry **entry_out,
701716
git_treebuilder *bld,
@@ -709,18 +724,8 @@ int git_treebuilder_insert(
709724

710725
assert(bld && id && filename);
711726

712-
if (!valid_filemode(filemode))
713-
return tree_error("failed to insert entry: invalid filemode for file", filename);
714-
715-
if (!valid_entry_name(bld->repo, filename))
716-
return tree_error("failed to insert entry: invalid name for a tree entry", filename);
717-
718-
if (git_oid_iszero(id))
719-
return tree_error("failed to insert entry: invalid null OID", filename);
720-
721-
if (filemode != GIT_FILEMODE_COMMIT &&
722-
!git_object__is_valid(bld->repo, id, otype_from_mode(filemode)))
723-
return tree_error("failed to insert entry: invalid object specified", filename);
727+
if ((error = check_entry(bld->repo, filename, id, filemode)) < 0)
728+
return error;
724729

725730
pos = git_strmap_lookup_index(bld->map, filename);
726731
if (git_strmap_valid_index(bld->map, pos)) {

tests/index/tests.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,30 @@ static void write_invalid_filename(git_repository *repo, const char *fn_orig)
639639
git__free(fn);
640640
}
641641

642+
void test_index_tests__write_tree_invalid_unowned_index(void)
643+
{
644+
git_index *idx;
645+
git_repository *repo;
646+
git_index_entry entry = {{0}};
647+
git_oid tree_id;
648+
649+
cl_git_pass(git_index_new(&idx));
650+
651+
cl_git_pass(git_oid_fromstr(&entry.id, "8312e0a89a9cbab77c732b6bc39b51a783e3a318"));
652+
entry.path = "foo";
653+
entry.mode = GIT_FILEMODE_BLOB;
654+
cl_git_pass(git_index_add(idx, &entry));
655+
656+
cl_git_pass(git_repository_init(&repo, "./invalid-id", 0));
657+
658+
cl_git_fail(git_index_write_tree_to(&tree_id, idx, repo));
659+
660+
git_index_free(idx);
661+
git_repository_free(repo);
662+
663+
cl_fixture_cleanup("invalid-id");
664+
}
665+
642666
/* Test that writing an invalid filename fails */
643667
void test_index_tests__write_invalid_filename(void)
644668
{
191 Bytes
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)