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

[PATCH 5/6] notes: avoid truncating the size of concatenated notes

From
Elia Pinto <gitter.spiros@gmail.com>
Date
Oct 30, 2026, 10:28 UTC
Message-ID
<21f5a4e009155e36865f6b01d59a00b644669e41.1793355390.git.gitter.spiros@gmail.com>
In-Reply-To
<cover.1793355390.git.gitter.spiros@gmail.com>

combine_notes_concatenate() reads both notes with odb_read_object(), which returns their sizes as size_t, but computes the size of the combined buffer in an "unsigned long". On platforms where that type is 32 bits wide, like Windows, two notes adding up to 4GiB or more give a small buf_len: we allocate that many bytes and then memcpy() the full contents of both notes into the buffer, writing far past its end.

The notes can come from a fetched notes ref. Besides notes merges with the "union" strategy and notes.rewriteMode=concatenate (the default), the function is also used when loading a notes tree that contains more than one note for the same object, e.g. at different fanout levels, so merely displaying such notes is enough to trigger it.

Compute the size as a size_t with st_add3(), and go through cast_size_t_to_ulong() when passing it to odb_write_object(), whose length parameter is still an "unsigned long". That makes us die on such platforms instead of writing a truncated blob, until the write API learns about size_t, too.

No test, as triggering this needs a platform with a 32-bit "long" and notes larger than 4GiB.

Signed-off-by: Elia Pinto <gitter.spiros@gmail.com>
---
 notes.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/notes.c b/notes.c
index ec9c2cb150..05da28b8d4 100644
--- a/notes.c
+++ b/notes.c
@@ -811,8 +811,7 @@ int combine_notes_concatenate(struct object_id *cur_oid,
 			      const struct object_id *new_oid)
 {
 	char *cur_msg = NULL, *new_msg = NULL, *buf;
-	unsigned long buf_len;
-	size_t cur_len, new_len;
+	size_t cur_len, new_len, buf_len;
 	enum object_type cur_type, new_type;
 	int ret;
 
@@ -839,7 +838,7 @@ int combine_notes_concatenate(struct object_id *cur_oid,
 		cur_len--;
 
 	/* concatenate cur_msg and new_msg into buf */
-	buf_len = cur_len + 2 + new_len;
+	buf_len = st_add3(cur_len, 2, new_len);
 	buf = (char *) xmalloc(buf_len);
 	memcpy(buf, cur_msg, cur_len);
 	buf[cur_len] = '\n';
@@ -850,7 +849,7 @@ int combine_notes_concatenate(struct object_id *cur_oid,
 
 	/* create a new blob object from buf */
 	ret = odb_write_object(the_repository->objects, buf,
-			       buf_len, OBJ_BLOB, cur_oid);
+			       cast_size_t_to_ulong(buf_len), OBJ_BLOB, cur_oid);
 	free(buf);
 	return ret;
 }
-- 
2.53.0
Previous: Elia PintoNext: Elia Pinto
Message 6 of 7 in “loose object size checks and a few size truncations”
  1. 0/6 loose object size checks and a few size truncationsElia Pinto, Oct 30, 2026
  2. 1/6 object-file: check size of inflated loose object against its headerElia Pinto, Oct 30, 2026
  3. 2/6 object-file: use size_t for loose object sizesElia Pinto, Oct 30, 2026
  4. 3/6 odb/source-loose: check object size when streaming loose objectsElia Pinto, Oct 30, 2026
  5. 4/6 cat-file: use size_t for the length passed to batch_write()Elia Pinto, Oct 30, 2026
  6. 5/6 notes: avoid truncating the size of concatenated notesElia Pinto, Oct 30, 2026
  7. 6/6 diff: use size_t in count_trailing_blank()Elia Pinto, Oct 30, 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.