git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 2/4] object-file: adapt `stream_object_signature()` to take a stream

From
Patrick Steinhardt <ps@pks.im>
Date
Feb 23, 2026, 09:50 UTC
Message-ID
<20260223-pks-fsck-fix-v1-2-c29036832b6e@pks.im>
In-Reply-To
<20260223-pks-fsck-fix-v1-0-c29036832b6e@pks.im>

The function `stream_object_signature()` is responsible for verifying whether the given object ID matches the actual hash of the object's contents. In contrast to `check_object_signature()` it does so in a streaming fashion so that we don't have to load the full object into memory.

In a subsequent commit we'll want to adapt one of its callsites to pass a preconstructed stream. Prepare for this by accepting a stream as input that the caller needs to assemble.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 object-file.c | 10 +++-------
 object-file.h |  4 +++-
 object.c      | 15 ++++++++++++---
 pack-check.c  | 12 +++++++++---
 4 files changed, 27 insertions(+), 14 deletions(-)
diff --git a/object-file.c b/object-file.c
index 1b62996ef0..ca2c4dddf3 100644
--- a/object-file.c
+++ b/object-file.c
@@ -129,18 +129,15 @@ int check_object_signature(struct repository *r, const struct object_id *oid,
 	return !oideq(oid, &real_oid) ? -1 : 0;
 }
 
-int stream_object_signature(struct repository *r, const struct object_id *oid)
+int stream_object_signature(struct repository *r,
+			    struct odb_read_stream *st,
+			    const struct object_id *oid)
 {
 	struct object_id real_oid;
-	struct odb_read_stream *st;
 	struct git_hash_ctx c;
 	char hdr[MAX_HEADER_LEN];
 	int hdrlen;
 
-	st = odb_read_stream_open(r->objects, oid, NULL);
-	if (!st)
-		return -1;
-
 	/* Generate the header */
 	hdrlen = format_object_header(hdr, sizeof(hdr), st->type, st->size);
 
@@ -160,7 +157,6 @@ int stream_object_signature(struct repository *r, const struct object_id *oid)
 		git_hash_update(&c, buf, readlen);
 	}
 	git_hash_final_oid(&real_oid, &c);
-	odb_read_stream_close(st);
 	return !oideq(oid, &real_oid) ? -1 : 0;
 }
 
diff --git a/object-file.h b/object-file.h
index a62d0de394..733d232309 100644
--- a/object-file.h
+++ b/object-file.h
@@ -164,7 +164,9 @@ int check_object_signature(struct repository *r, const struct object_id *oid,
  * Try reading the object named with "oid" using
  * the streaming interface and rehash it to do the same.
  */
-int stream_object_signature(struct repository *r, const struct object_id *oid);
+int stream_object_signature(struct repository *r,
+			    struct odb_read_stream *stream,
+			    const struct object_id *oid);
 
 enum finalize_object_file_flags {
 	FOF_SKIP_COLLISION_CHECK = 1,
diff --git a/object.c b/object.c
index 4669b8d65e..56d79d77b4 100644
--- a/object.c
+++ b/object.c
@@ -6,6 +6,7 @@
 #include "object.h"
 #include "replace-object.h"
 #include "object-file.h"
+#include "odb/streaming.h"
 #include "blob.h"
 #include "statinfo.h"
 #include "tree.h"
@@ -330,9 +331,17 @@ struct object *parse_object_with_flags(struct repository *r,
 
 	if ((!obj || obj->type == OBJ_NONE || obj->type == OBJ_BLOB) &&
 	    odb_read_object_info(r->objects, oid, NULL) == OBJ_BLOB) {
-		if (!skip_hash && stream_object_signature(r, repl) < 0) {
-			error(_("hash mismatch %s"), oid_to_hex(oid));
-			return NULL;
+		if (!skip_hash) {
+			struct odb_read_stream *stream = odb_read_stream_open(r->objects, oid, NULL);
+			if (!stream || stream_object_signature(r, stream, repl) < 0) {
+				error(_("hash mismatch %s"), oid_to_hex(oid));
+				if (stream)
+					odb_read_stream_close(stream);
+				return NULL;
+			}
+
+			if (stream)
+				odb_read_stream_close(stream);
 		}
 		parse_blob_buffer(lookup_blob(r, oid));
 		return lookup_object(r, oid);
diff --git a/pack-check.c b/pack-check.c
index 67cb2cf72f..46782a29d5 100644
--- a/pack-check.c
+++ b/pack-check.c
@@ -9,6 +9,7 @@
 #include "packfile.h"
 #include "object-file.h"
 #include "odb.h"
+#include "odb/streaming.h"
 
 struct idx_entry {
 	off_t                offset;
@@ -104,6 +105,7 @@ static int verify_packfile(struct repository *r,
 	QSORT(entries, nr_objects, compare_entries);
 
 	for (i = 0; i < nr_objects; i++) {
+		struct odb_read_stream *stream = NULL;
 		void *data;
 		struct object_id oid;
 		enum object_type type;
@@ -152,7 +154,9 @@ static int verify_packfile(struct repository *r,
 							type) < 0)
 			err = error("packed %s from %s is corrupt",
 				    oid_to_hex(&oid), p->pack_name);
-		else if (!data && stream_object_signature(r, &oid) < 0)
+		else if (!data &&
+			 (!(stream = odb_read_stream_open(r->objects, &oid, NULL)) ||
+			  stream_object_signature(r, stream, &oid) < 0))
 			err = error("packed %s from %s is corrupt",
 				    oid_to_hex(&oid), p->pack_name);
 		else if (fn) {
@@ -163,12 +167,14 @@ static int verify_packfile(struct repository *r,
 		}
 		if (((base_count + i) & 1023) == 0)
 			display_progress(progress, base_count + i);
-		free(data);
 
+		if (stream)
+			odb_read_stream_close(stream);
+		free(data);
 	}
+
 	display_progress(progress, base_count + i);
 	free(entries);
-
 	return err;
 }
 
-- 
2.53.0.414.gf7e9f6c205.dirty
Previous: Eric SunshineNext: Jeff King
Message 6 of 26 in “pack-check: fix verification of large objects”
  1. 0/4 pack-check: fix verification of large objectsPatrick Steinhardt, Feb 23, 2026
  2. 1/4 t/helper: improve "genrandom" test helperPatrick Steinhardt, Feb 23, 2026
  3. Jeff KingFeb 23, 2026
  4. Patrick SteinhardtFeb 23, 2026
  5. Eric SunshineFeb 23, 2026
  6. 2/4 object-file: adapt `stream_object_signature()` to take a streamPatrick Steinhardt, Feb 23, 2026
  7. Jeff KingFeb 23, 2026
  8. Patrick SteinhardtFeb 23, 2026
  9. Jeff KingFeb 23, 2026
  10. 3/4 packfile: expose function to read object stream for an offsetPatrick Steinhardt, Feb 23, 2026
  11. Jeff KingFeb 23, 2026
  12. Patrick SteinhardtFeb 23, 2026
  13. Jeff KingFeb 23, 2026
  14. Patrick SteinhardtFeb 23, 2026
  15. 4/4 pack-check: fix verification of large objectsPatrick Steinhardt, Feb 23, 2026
  16. Jeff KingFeb 23, 2026
  17. Patrick SteinhardtFeb 23, 2026
  18. Jeff KingFeb 23, 2026
  19. Patrick SteinhardtFeb 23, 2026
  20. Junio C HamanoFeb 23, 2026
  21. Patrick SteinhardtFeb 24, 2026
  22. 0/4 pack-check: fix verification of large objectsPatrick Steinhardt, Feb 23, 2026
  23. 1/4 t/helper: improve "genrandom" test helperPatrick Steinhardt, Feb 23, 2026
  24. 2/4 object-file: adapt `stream_object_signature()` to take a streamPatrick Steinhardt, Feb 23, 2026
  25. 3/4 packfile: expose function to read object stream for an offsetPatrick Steinhardt, Feb 23, 2026
  26. 4/4 pack-check: fix verification of large objectsPatrick Steinhardt, Feb 23, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.