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

[PATCH v2] builtin/blame: fix out-of-bounds read with excessive `--abbrev`

From
Patrick Steinhardt <ps@pks.im>
Date
Jan 9, 2025, 11:48 UTC
Message-ID
<20250109-b4-pks-blame-truncate-hash-length-v2-1-589c81a6ddb0@pks.im>
In-Reply-To
<20250109-b4-pks-blame-truncate-hash-length-v1-1-9ad4bb09e059@pks.im>

In 6411a0a896 (builtin/blame: fix type of `length` variable when emitting object ID, 2024-12-06) we have fixed the type of the `length` variable. In order to avoid a cast from `size_t` to `int` in the call to printf(3p) with the "%.*s" formatter we have converted the code to instead use fwrite(3p), which accepts the length as a `size_t`.

It was reported though that this makes us read over the end of the OID array when the provided `--abbrev=` length exceeds the length of the object ID. This is because fwrite(3p) of course doesn't stop when it sees a NUL byte, whereas printf(3p) does.

Fix the bug by reverting back to printf(3p) and culling the provided length to `GIT_MAX_HEXSZ` to keep it from overflowing when cast to an `int`.

Reported-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
This fixes the issue reported in [1]. Thanks!
Changes in v2:
  - Take into account that we may strip ^, * and ? indicators by moving
    around the check.
  - Fix the testcase so that it actually fails without the fix.
  - Link to v1: https://lore.kernel.org/r/20250109-b4-pks-blame-truncate-hash-length-v1-1-9ad4bb09e059@pks.im
Patrick
[1]: <4d812802-afbc-4635-7a19-73896fcda625@gmx.de>
---
 builtin/blame.c  | 5 ++++-
 t/t8002-blame.sh | 4 ++++
 2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/builtin/blame.c b/builtin/blame.c
index 867032e4c16878ffd56df8a73162b89ca4bd2694..f92e487bed22eec576a4716f2e654cb61efb9903 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -505,7 +505,10 @@ static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int
 			length--;
 			putchar('?');
 		}
-		fwrite(hex, 1, length, stdout);
+
+		if (length > GIT_MAX_HEXSZ)
+			length = GIT_MAX_HEXSZ;
+		printf("%.*s", (int)length, hex);
 		if (opt & OUTPUT_ANNOTATE_COMPAT) {
 			const char *name;
 			if (opt & OUTPUT_SHOW_EMAIL)
diff --git a/t/t8002-blame.sh b/t/t8002-blame.sh
index 0147de304b4d104cc7f05ea1f8d68f1a07ceb80d..7cf6e0253a5bbd4d6e438e627dc18b47eac4df66 100755
--- a/t/t8002-blame.sh
+++ b/t/t8002-blame.sh
@@ -126,6 +126,10 @@ test_expect_success '--no-abbrev works like --abbrev with full length' '
 	check_abbrev $hexsz --no-abbrev
 '
 
+test_expect_success 'blame --abbrev gets truncated' '
+	check_abbrev $hexsz --abbrev=9000 HEAD
+'
+
 test_expect_success '--exclude-promisor-objects does not BUG-crash' '
 	test_must_fail git blame --exclude-promisor-objects one
 '

---
base-commit: 14650065b76b28d3cfa9453356ac5669b19e706e
change-id: 20250109-b4-pks-blame-truncate-hash-length-c875cac66d71
Previous: Patrick SteinhardtNext: shejialuo
Message 8 of 18 in “builtin/blame: fix out-of-bounds read with excessive `--abbrev`”
  1. builtin/blame: fix out-of-bounds read with excessive `--abbrev`Patrick Steinhardt, Jan 9, 2025
  2. Kristoffer HaugsbakkJan 9, 2025
  3. Johannes SchindelinJan 9, 2025
  4. Patrick SteinhardtJan 9, 2025
  5. Johannes SchindelinJan 9, 2025
  6. Johannes SchindelinJan 10, 2025
  7. Patrick SteinhardtJan 10, 2025
  8. builtin/blame: fix out-of-bounds read with excessive `--abbrev`Patrick Steinhardt, Jan 9, 2025
  9. shejialuoJan 9, 2025
  10. Johannes SchindelinJan 9, 2025
  11. shejialuoJan 10, 2025
  12. Johannes SchindelinJan 9, 2025
  13. Junio C HamanoJan 9, 2025
  14. 0/2 builtin/blame: fix out-of-bounds reads and writesPatrick Steinhardt, Jan 10, 2025
  15. 1/2 builtin/blame: fix out-of-bounds read with excessive `--abbrev`Patrick Steinhardt, Jan 10, 2025
  16. 2/2 builtin/blame: fix out-of-bounds write with blank boundary commitsPatrick Steinhardt, Jan 10, 2025
  17. Johannes SchindelinJan 10, 2025
  18. Junio C HamanoJan 10, 2025

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.