diff options
author | Edward Thomson <ethomson@github.com> | 2016-02-23 15:00:27 -0500 |
---|---|---|
committer | Edward Thomson <ethomson@github.com> | 2016-02-28 12:38:40 -0500 |
commit | 2bbc7d3e564ed262e9555ea4fd081ece5ceb3bff (patch) | |
tree | d874a213c212c247b57cebbb37140f01777bde6f | |
parent | ef63bab306a2a85d15e62bfb73f49ae11f2b5df6 (diff) | |
download | libgit2-2bbc7d3e564ed262e9555ea4fd081ece5ceb3bff.tar.gz |
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.
-rw-r--r-- | src/tree.c | 15 | ||||
-rw-r--r-- | tests/object/tree/write.c | 55 |
2 files changed, 70 insertions, 0 deletions
diff --git a/src/tree.c b/src/tree.c index cfceb3f33..2c3151546 100644 --- a/src/tree.c +++ b/src/tree.c @@ -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); diff --git a/tests/object/tree/write.c b/tests/object/tree/write.c index 5433e5f03..4cd1607d8 100644 --- a/tests/object/tree/write.c +++ b/tests/object/tree/write.c @@ -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); +} + |