object-file: fix memory leak in `force_object_loose()`
We return an error when converting the given object to the compatibility hash algorithm fails. This early return causes a memory leak though, because we don't free the content buffer that we've already read before via `odb_read_object_info_extended()`. Plug the memory leak by creating a common exit path where the buffer gets free'd. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Patrick Steinhardt committed
Jul 17, 2026 at 11:32 UTC
0e002f6dc74841324687284e6a3ae4a6061c0c73
1 file changed
+18
-8
object-file.c
+18
-8
index 5b07530950..067a63a4f1 100644
--- a/object-file.c
+++ b/object-file.c
@@ -898,7 +898,7 @@ int force_object_loose(struct odb_source *source,
{
struct odb_source_files *files = odb_source_files_downcast(source);
const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
- void *buf;
+ void *buf = NULL;
size_t len;
struct object_info oi = OBJECT_INFO_INIT;
struct object_id compat_oid;
@@ -916,19 +916,29 @@ int force_object_loose(struct odb_source *source,
oi.typep = &type;
oi.sizep = &len;
oi.contentp = &buf;
- if (odb_read_object_info_extended(source->odb, oid, &oi, 0))
- return error(_("cannot read object for %s"), oid_to_hex(oid));
+ if (odb_read_object_info_extended(source->odb, oid, &oi, 0)) {
+ ret = error(_("cannot read object for %s"), oid_to_hex(oid));
+ goto out;
+ }
+
if (compat) {
- if (repo_oid_to_algop(source->odb->repo, oid, compat, &compat_oid))
- return error(_("cannot map object %s to %s"),
- oid_to_hex(oid), compat->name);
+ if (repo_oid_to_algop(source->odb->repo, oid, compat, &compat_oid)) {
+ ret = error(_("cannot map object %s to %s"),
+ oid_to_hex(oid), compat->name);
+ goto out;
+ }
}
+
hdrlen = format_object_header(hdr, sizeof(hdr), type, len);
ret = write_loose_object(files->loose, oid, hdr, hdrlen, buf, len, mtime, 0);
- if (!ret && compat)
+ if (ret)
+ goto out;
+
+ if (compat)
ret = repo_add_loose_object_map(files->loose, oid, &compat_oid);
- free(buf);
+out:
+ free(buf);
return ret;
}