Skip to content

Commit 3abb8fc

Browse files
committed
fix use-after-free causing intermittent failures in Repository::statistics()
git_reference_target just returns a pointer to the git_reference's oid, it does not clone it so freeing the reference then wipes the oid
1 parent f353fe1 commit 3abb8fc

File tree

1 file changed

+9
-6
lines changed

1 file changed

+9
-6
lines changed

generate/templates/manual/repository/statistics.cc

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,11 +1020,13 @@ int RepoAnalysis::storeAndCountRefs()
10201020
}
10211021

10221022
// obtain peeled oid of the reference
1023-
const git_oid *oid_ref {nullptr};
1023+
bool found_oid = false;
1024+
git_oid oid_ref;
10241025
switch (git_reference_type(ref))
10251026
{
10261027
case GIT_REFERENCE_DIRECT:
1027-
oid_ref = git_reference_target(ref);
1028+
git_oid_cpy(&oid_ref, git_reference_target(ref));
1029+
found_oid = true;
10281030
break;
10291031

10301032
case GIT_REFERENCE_SYMBOLIC:
@@ -1035,7 +1037,8 @@ int RepoAnalysis::storeAndCountRefs()
10351037
git_strarray_dispose(&ref_list);
10361038
return errorCode;
10371039
}
1038-
oid_ref = git_reference_target(ref_resolved);
1040+
git_oid_cpy(&oid_ref, git_reference_target(ref_resolved));
1041+
found_oid = true;
10391042
git_reference_free(ref_resolved);
10401043
}
10411044
break;
@@ -1045,17 +1048,17 @@ int RepoAnalysis::storeAndCountRefs()
10451048
}
10461049

10471050
// store object's oid and type
1048-
if (oid_ref != nullptr)
1051+
if (found_oid)
10491052
{
10501053
git_object *target {nullptr};
1051-
if ((errorCode = git_object_lookup(&target, m_repo, oid_ref, GIT_OBJECT_ANY)) != GIT_OK) {
1054+
if ((errorCode = git_object_lookup(&target, m_repo, &oid_ref, GIT_OBJECT_ANY)) != GIT_OK) {
10521055
git_reference_free(ref);
10531056
git_strarray_dispose(&ref_list);
10541057
return errorCode;
10551058
}
10561059

10571060
m_peeledRefs.emplace(std::make_pair(
1058-
std::string(reinterpret_cast<const char *>(oid_ref->id), GIT_OID_RAWSZ),
1061+
std::string(reinterpret_cast<const char *>(oid_ref.id), GIT_OID_RAWSZ),
10591062
git_object_type(target)));
10601063

10611064
git_object_free(target);

0 commit comments

Comments
 (0)