diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2018-01-29 22:37:12 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-01-29 22:37:12 +0000 |
commit | 895fd51a434ac50ebd53e996bd9149302ca3e134 (patch) | |
tree | 0011f4797b360cf1a045c73af82411816f833347 | |
parent | c935b926c90a1b5b35caa7b8fb8dedd54b235ec5 (diff) | |
parent | 275f103d4c515d40c73cc17ae7880f1091414393 (diff) | |
download | libgit2-895fd51a434ac50ebd53e996bd9149302ca3e134.tar.gz |
Merge pull request #4474 from pks-t/pks/null-oid
Special-casing null OIDs
-rw-r--r-- | src/odb.c | 26 | ||||
-rw-r--r-- | src/tree.c | 6 | ||||
-rw-r--r-- | tests/object/tree/write.c | 11 | ||||
-rw-r--r-- | tests/odb/backend/simple.c | 18 |
4 files changed, 60 insertions, 1 deletions
@@ -53,6 +53,7 @@ static git_cache *odb_cache(git_odb *odb) static int odb_otype_fast(git_otype *type_p, git_odb *db, const git_oid *id); static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_depth); +static int error_null_oid(int error, const char *message); static git_otype odb_hardcoded_type(const git_oid *id) { @@ -735,6 +736,9 @@ int git_odb_exists(git_odb *db, const git_oid *id) assert(db && id); + if (git_oid_iszero(id)) + return 0; + if ((object = git_cache_get_raw(odb_cache(db), id)) != NULL) { git_odb_object_free(object); return 1; @@ -958,6 +962,11 @@ int git_odb__read_header_or_object( assert(db && id && out && len_p && type_p); + *out = NULL; + + if (git_oid_iszero(id)) + return error_null_oid(GIT_ENOTFOUND, "cannot read object"); + if ((object = git_cache_get_raw(odb_cache(db), id)) != NULL) { *len_p = object->cached.size; *type_p = object->cached.type; @@ -965,7 +974,6 @@ int git_odb__read_header_or_object( return 0; } - *out = NULL; error = odb_read_header_1(len_p, type_p, db, id, false); if (error == GIT_ENOTFOUND && !git_odb_refresh(db)) @@ -1057,6 +1065,9 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id) assert(out && db && id); + if (git_oid_iszero(id)) + return error_null_oid(GIT_ENOTFOUND, "cannot read object"); + *out = git_cache_get_raw(odb_cache(db), id); if (*out != NULL) return 0; @@ -1078,6 +1089,9 @@ static int odb_otype_fast(git_otype *type_p, git_odb *db, const git_oid *id) size_t _unused; int error; + if (git_oid_iszero(id)) + return error_null_oid(GIT_ENOTFOUND, "cannot get object type"); + if ((object = git_cache_get_raw(odb_cache(db), id)) != NULL) { *type_p = object->cached.type; return 0; @@ -1231,6 +1245,10 @@ int git_odb_write( assert(oid && db); git_odb_hash(oid, data, len, type); + + if (git_oid_iszero(oid)) + return error_null_oid(GIT_EINVALID, "cannot write object"); + if (git_odb__freshen(db, oid)) return 0; @@ -1484,6 +1502,12 @@ int git_odb__error_notfound( return GIT_ENOTFOUND; } +static int error_null_oid(int error, const char *message) +{ + giterr_set(GITERR_ODB, "odb: %s: null OID cannot exist", message); + return error; +} + int git_odb__error_ambiguous(const char *message) { giterr_set(GITERR_ODB, "ambiguous SHA1 prefix - %s", message); diff --git a/src/tree.c b/src/tree.c index 75fde2c8f..6a136a6b7 100644 --- a/src/tree.c +++ b/src/tree.c @@ -498,6 +498,9 @@ static int append_entry( if (!valid_entry_name(bld->repo, filename)) return tree_error("failed to insert entry: invalid name for a tree entry", filename); + if (git_oid_iszero(id)) + return tree_error("failed to insert entry: invalid null OID for a tree entry", filename); + entry = alloc_entry(filename, strlen(filename), id); GITERR_CHECK_ALLOC(entry); @@ -740,6 +743,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_oid_iszero(id)) + return tree_error("failed to insert entry: invalid null OID", filename); + if (filemode != GIT_FILEMODE_COMMIT && !git_object__is_valid(bld->repo, id, otype_from_mode(filemode))) return tree_error("failed to insert entry: invalid object specified", filename); diff --git a/tests/object/tree/write.c b/tests/object/tree/write.c index a9decf9c1..9690ec4d7 100644 --- a/tests/object/tree/write.c +++ b/tests/object/tree/write.c @@ -512,3 +512,14 @@ void test_object_tree_write__object_validity(void) test_inserting_submodule(); } +void test_object_tree_write__invalid_null_oid(void) +{ + git_treebuilder *bld; + git_oid null_oid = {{0}}; + + cl_git_pass(git_treebuilder_new(&bld, g_repo, NULL)); + cl_git_fail(git_treebuilder_insert(NULL, bld, "null_oid_file", &null_oid, GIT_FILEMODE_BLOB)); + cl_assert(giterr_last() && strstr(giterr_last()->message, "null OID") != NULL); + + git_treebuilder_free(bld); +} diff --git a/tests/odb/backend/simple.c b/tests/odb/backend/simple.c index c0fcd403b..f4d29cc76 100644 --- a/tests/odb/backend/simple.c +++ b/tests/odb/backend/simple.c @@ -230,3 +230,21 @@ void test_odb_backend_simple__exists_with_highly_ambiguous_prefix(void) cl_git_pass(git_odb_exists_prefix(&found, _odb, &_oid, 40)); cl_assert(git_oid_equal(&found, &_oid)); } + +void test_odb_backend_simple__null_oid_is_ignored(void) +{ + const fake_object objs[] = { + { "0000000000000000000000000000000000000000", "null oid content" }, + { NULL, NULL } + }; + git_oid null_oid = {{0}}; + git_odb_object *obj; + + setup_backend(objs); + + cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION, 0)); + cl_assert(!git_odb_exists(_odb, &null_oid)); + + cl_git_fail_with(GIT_ENOTFOUND, git_odb_read(&obj, _odb, &null_oid)); + cl_assert(giterr_last() && strstr(giterr_last()->message, "null OID")); +} |