Skip to content

Commit 895fd51

Browse files
authored
Merge pull request libgit2#4474 from pks-t/pks/null-oid
Special-casing null OIDs
2 parents c935b92 + 275f103 commit 895fd51

File tree

4 files changed

+60
-1
lines changed

4 files changed

+60
-1
lines changed

src/odb.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ static git_cache *odb_cache(git_odb *odb)
5353

5454
static int odb_otype_fast(git_otype *type_p, git_odb *db, const git_oid *id);
5555
static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_depth);
56+
static int error_null_oid(int error, const char *message);
5657

5758
static git_otype odb_hardcoded_type(const git_oid *id)
5859
{
@@ -735,6 +736,9 @@ int git_odb_exists(git_odb *db, const git_oid *id)
735736

736737
assert(db && id);
737738

739+
if (git_oid_iszero(id))
740+
return 0;
741+
738742
if ((object = git_cache_get_raw(odb_cache(db), id)) != NULL) {
739743
git_odb_object_free(object);
740744
return 1;
@@ -958,14 +962,18 @@ int git_odb__read_header_or_object(
958962

959963
assert(db && id && out && len_p && type_p);
960964

965+
*out = NULL;
966+
967+
if (git_oid_iszero(id))
968+
return error_null_oid(GIT_ENOTFOUND, "cannot read object");
969+
961970
if ((object = git_cache_get_raw(odb_cache(db), id)) != NULL) {
962971
*len_p = object->cached.size;
963972
*type_p = object->cached.type;
964973
*out = object;
965974
return 0;
966975
}
967976

968-
*out = NULL;
969977
error = odb_read_header_1(len_p, type_p, db, id, false);
970978

971979
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)
10571065

10581066
assert(out && db && id);
10591067

1068+
if (git_oid_iszero(id))
1069+
return error_null_oid(GIT_ENOTFOUND, "cannot read object");
1070+
10601071
*out = git_cache_get_raw(odb_cache(db), id);
10611072
if (*out != NULL)
10621073
return 0;
@@ -1078,6 +1089,9 @@ static int odb_otype_fast(git_otype *type_p, git_odb *db, const git_oid *id)
10781089
size_t _unused;
10791090
int error;
10801091

1092+
if (git_oid_iszero(id))
1093+
return error_null_oid(GIT_ENOTFOUND, "cannot get object type");
1094+
10811095
if ((object = git_cache_get_raw(odb_cache(db), id)) != NULL) {
10821096
*type_p = object->cached.type;
10831097
return 0;
@@ -1231,6 +1245,10 @@ int git_odb_write(
12311245
assert(oid && db);
12321246

12331247
git_odb_hash(oid, data, len, type);
1248+
1249+
if (git_oid_iszero(oid))
1250+
return error_null_oid(GIT_EINVALID, "cannot write object");
1251+
12341252
if (git_odb__freshen(db, oid))
12351253
return 0;
12361254

@@ -1484,6 +1502,12 @@ int git_odb__error_notfound(
14841502
return GIT_ENOTFOUND;
14851503
}
14861504

1505+
static int error_null_oid(int error, const char *message)
1506+
{
1507+
giterr_set(GITERR_ODB, "odb: %s: null OID cannot exist", message);
1508+
return error;
1509+
}
1510+
14871511
int git_odb__error_ambiguous(const char *message)
14881512
{
14891513
giterr_set(GITERR_ODB, "ambiguous SHA1 prefix - %s", message);

src/tree.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,9 @@ static int append_entry(
498498
if (!valid_entry_name(bld->repo, filename))
499499
return tree_error("failed to insert entry: invalid name for a tree entry", filename);
500500

501+
if (git_oid_iszero(id))
502+
return tree_error("failed to insert entry: invalid null OID for a tree entry", filename);
503+
501504
entry = alloc_entry(filename, strlen(filename), id);
502505
GITERR_CHECK_ALLOC(entry);
503506

@@ -740,6 +743,9 @@ int git_treebuilder_insert(
740743
if (!valid_entry_name(bld->repo, filename))
741744
return tree_error("failed to insert entry: invalid name for a tree entry", filename);
742745

746+
if (git_oid_iszero(id))
747+
return tree_error("failed to insert entry: invalid null OID", filename);
748+
743749
if (filemode != GIT_FILEMODE_COMMIT &&
744750
!git_object__is_valid(bld->repo, id, otype_from_mode(filemode)))
745751
return tree_error("failed to insert entry: invalid object specified", filename);

tests/object/tree/write.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,3 +512,14 @@ void test_object_tree_write__object_validity(void)
512512
test_inserting_submodule();
513513
}
514514

515+
void test_object_tree_write__invalid_null_oid(void)
516+
{
517+
git_treebuilder *bld;
518+
git_oid null_oid = {{0}};
519+
520+
cl_git_pass(git_treebuilder_new(&bld, g_repo, NULL));
521+
cl_git_fail(git_treebuilder_insert(NULL, bld, "null_oid_file", &null_oid, GIT_FILEMODE_BLOB));
522+
cl_assert(giterr_last() && strstr(giterr_last()->message, "null OID") != NULL);
523+
524+
git_treebuilder_free(bld);
525+
}

tests/odb/backend/simple.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,3 +230,21 @@ void test_odb_backend_simple__exists_with_highly_ambiguous_prefix(void)
230230
cl_git_pass(git_odb_exists_prefix(&found, _odb, &_oid, 40));
231231
cl_assert(git_oid_equal(&found, &_oid));
232232
}
233+
234+
void test_odb_backend_simple__null_oid_is_ignored(void)
235+
{
236+
const fake_object objs[] = {
237+
{ "0000000000000000000000000000000000000000", "null oid content" },
238+
{ NULL, NULL }
239+
};
240+
git_oid null_oid = {{0}};
241+
git_odb_object *obj;
242+
243+
setup_backend(objs);
244+
245+
cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION, 0));
246+
cl_assert(!git_odb_exists(_odb, &null_oid));
247+
248+
cl_git_fail_with(GIT_ENOTFOUND, git_odb_read(&obj, _odb, &null_oid));
249+
cl_assert(giterr_last() && strstr(giterr_last()->message, "null OID"));
250+
}

0 commit comments

Comments
 (0)