Commit 2bbc7d3e by Edward Thomson

treebuilder: validate tree entries (optionally)

When `GIT_OPT_ENABLE_STRICT_OBJECT_CREATION` is turned on, validate
the tree and parent ids given to treebuilder insertion.
parent ef63bab3
......@@ -726,6 +726,18 @@ on_error:
return -1;
}
static git_otype otype_from_mode(git_filemode_t filemode)
{
switch (filemode) {
case GIT_FILEMODE_TREE:
return GIT_OBJ_TREE;
case GIT_FILEMODE_COMMIT:
return GIT_OBJ_COMMIT;
default:
return GIT_OBJ_BLOB;
}
}
int git_treebuilder_insert(
const git_tree_entry **entry_out,
git_treebuilder *bld,
......@@ -745,6 +757,9 @@ int git_treebuilder_insert(
if (!valid_entry_name(bld->repo, filename))
return tree_error("Failed to insert entry. Invalid name for a tree entry", filename);
if (!git_object__is_valid(bld->repo, id, otype_from_mode(filemode)))
return tree_error("Failed to insert entry; invalid object specified", filename);
pos = git_strmap_lookup_index(bld->map, filename);
if (git_strmap_valid_index(bld->map, pos)) {
entry = git_strmap_value_at(bld->map, pos);
......
......@@ -18,6 +18,8 @@ void test_object_tree_write__initialize(void)
void test_object_tree_write__cleanup(void)
{
cl_git_sandbox_cleanup();
cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, 0));
}
void test_object_tree_write__from_memory(void)
......@@ -440,3 +442,56 @@ void test_object_tree_write__protect_filesystems(void)
git_treebuilder_free(builder);
}
static void test_invalid_objects(bool should_allow_invalid)
{
git_treebuilder *builder;
git_oid valid_blob_id, invalid_blob_id, valid_tree_id, invalid_tree_id;
#define assert_allowed(expr) \
clar__assert(!(expr) == should_allow_invalid, __FILE__, __LINE__, \
(should_allow_invalid ? \
"Expected function call to succeed: " #expr : \
"Expected function call to fail: " #expr), \
NULL, 1)
cl_git_pass(git_oid_fromstr(&valid_blob_id, blob_oid));
cl_git_pass(git_oid_fromstr(&invalid_blob_id,
"1234567890123456789012345678901234567890"));
cl_git_pass(git_oid_fromstr(&valid_tree_id, first_tree));
cl_git_pass(git_oid_fromstr(&invalid_tree_id,
"0000000000111111111122222222223333333333"));
cl_git_pass(git_treebuilder_new(&builder, g_repo, NULL));
/* test valid blobs and trees (these should always pass) */
cl_git_pass(git_treebuilder_insert(NULL, builder, "file.txt", &valid_blob_id, GIT_FILEMODE_BLOB));
cl_git_pass(git_treebuilder_insert(NULL, builder, "folder", &valid_tree_id, GIT_FILEMODE_TREE));
/* replace valid files and folders with invalid ones */
assert_allowed(git_treebuilder_insert(NULL, builder, "file.txt", &invalid_blob_id, GIT_FILEMODE_BLOB));
assert_allowed(git_treebuilder_insert(NULL, builder, "folder", &invalid_blob_id, GIT_FILEMODE_BLOB));
/* insert new invalid files and folders */
assert_allowed(git_treebuilder_insert(NULL, builder, "invalid_file.txt", &invalid_blob_id, GIT_FILEMODE_BLOB));
assert_allowed(git_treebuilder_insert(NULL, builder, "invalid_folder", &invalid_blob_id, GIT_FILEMODE_BLOB));
/* insert valid blobs as trees and trees as blobs */
assert_allowed(git_treebuilder_insert(NULL, builder, "file_as_folder", &valid_blob_id, GIT_FILEMODE_TREE));
assert_allowed(git_treebuilder_insert(NULL, builder, "folder_as_file.txt", &valid_tree_id, GIT_FILEMODE_BLOB));
#undef assert_allowed
git_treebuilder_free(builder);
}
void test_object_tree_write__object_validity(void)
{
/* Ensure that we can add invalid objects by default */
test_invalid_objects(true);
/* Ensure that we can turn on validation */
cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, 1));
test_invalid_objects(false);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment