From: Toon Claes Date: Mon, 12 Jan 2026 16:17:41 GMT Subject: [PATCH] last-modified: verify revision argument is a commit-ish Message-ID: <20260112-toon-last-modified-tree-v1-1-ecbc78341f76@iotcl.com> Passing a tree OID to git-last-modified(1) would trigger BUG behavior. git last-modified HEAD^{tree} BUG: builtin/last-modified.c:456: paths remaining beyond boundary in last-modified Fix this error by verifying the parsed revision is peels to a commit-ish. While at it, also fix a memory leak in populate_paths_from_revs(). Reported-by: Gusted Signed-off-by: Toon Claes --- Recently there was a bug reported[1] passing a tree OID triggers a BUG: $ git last-modified fb06ce04173d47aaaa498385621cba8b8dfd7584 BUG: builtin/last-modified.c:456: paths remaining beyond boundary in last-modified [1] 690163 IOT instruction (core dumped) git last-modified `fb06ce04173d47aaaa498385621cba8b8dfd7584` is the tree commit id of web_src. I suppose this should've returned a nice error message or blank output. Fix this bug by checking the revision argument. [1]: https://lore.kernel.org/git/03f96860-29fc-42a7-a220-c3ec65eb8516@codeberg.org/ --- builtin/last-modified.c | 15 +++++++++++---- t/t8020-last-modified.sh | 5 +++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/builtin/last-modified.c b/builtin/last-modified.c index c80f0535f6..cac94e384d 100644 --- a/builtin/last-modified.c +++ b/builtin/last-modified.c @@ -123,7 +123,7 @@ static void add_path_from_diff(struct diff_queue_struct *q, static int populate_paths_from_revs(struct last_modified *lm) { - int num_interesting = 0; + int num_interesting = 0, ret = 0; struct diff_options diffopt; /* @@ -145,8 +145,15 @@ static int populate_paths_from_revs(struct last_modified *lm) if (obj->item->flags & UNINTERESTING) continue; - if (num_interesting++) - return error(_("last-modified can only operate on one tree at a time")); + if (num_interesting++) { + ret = error(_("last-modified can only operate on one tree at a time")); + break; + } + + if (!repo_peel_to_type(lm->rev.repo, obj->path, 0, obj->item, OBJ_COMMIT)) { + ret = error(_("revision argument is not a commit-ish")); + break; + } diff_tree_oid(lm->rev.repo->hash_algo->empty_tree, &obj->item->oid, "", &diffopt); @@ -154,7 +161,7 @@ static int populate_paths_from_revs(struct last_modified *lm) } clear_pathspec(&diffopt.pathspec); - return 0; + return ret; } static void last_modified_emit(struct last_modified *lm, diff --git a/t/t8020-last-modified.sh b/t/t8020-last-modified.sh index 50f4312f71..d0d52add05 100755 --- a/t/t8020-last-modified.sh +++ b/t/t8020-last-modified.sh @@ -235,4 +235,9 @@ test_expect_success 'last-modified complains about unknown arguments' ' grep "unknown last-modified argument: --foo" err ' +test_expect_success 'last-modified expects commit-ish' ' + test_must_fail git last-modified HEAD^{tree} 2>err && + grep "revision argument is not a commit-ish" err +' + test_done --- base-commit: d529f3a197364881746f558e5652f0236131eb86 change-id: 20260112-toon-last-modified-tree-fdd96b2feaf7