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

[PATCH 6/6] revision: retain argv NULL invariant in setup_revisions()

From
Jeff King <peff@peff.net>
Date
Sep 19, 2025, 22:51 UTC
Message-ID
<20250919225146.GF594545@coredump.intra.peff.net>
In-Reply-To
<20250919223351.GA3906184@coredump.intra.peff.net>

In an argc/argv pair, the entry for argv[argc] is generally NULL. You can iterate by counting up to argc, or by looking for the NULL entry in argv.

When we pass such a pair to setup_revisions(), it shrinks argc to account for the options we consumed and returns the result to the caller. But it doesn't touch the entries after the reduced argc. So argv[argc] will be left pointing at some arbitrary entry rather than NULL.

This isn't the source of any known bugs, since all callers are aware of the limitation and act accordingly. But it's a possible gotcha that may be easy to miss.

Let's set the new argv[argc] to NULL, taking care to free it if the caller asked us to do so.

It is tempting to do likewise for all of the entries afterwards, too, as some of them may also need to be freed (e.g., if coming from a strvec). But doing so isn't entirely trivial, as we munge argc in the function (e.g., when we find "--" and move all of the entries after it into the prune_data list). It would be possible with some light refactoring, but it's probably not worth it. Nobody should ever look at them (they are beyond the revised argc and past the NULL argv entry) outside of strvec cleanup, and setup_revisions_from_strvec() already handles this case.

There's one other interesting gotcha: many callers which do not want to provide arguments just pass 0/NULL for argc/argv. We need to check for this case before assigning the final NULL.

Signed-off-by: Jeff King <peff@peff.net>
---
 revision.c | 6 ++++++
 1 file changed, 6 insertions(+)
diff --git a/revision.c b/revision.c
index f50f5d8ea2..806a1c4c24 100644
--- a/revision.c
+++ b/revision.c
@@ -3192,6 +3192,12 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
 		revs->show_notes_given = 1;
 	}
 
+	if (argv) {
+		if (opt && opt->free_removed_argv_elements)
+			free((char *)argv[left]);
+		argv[left] = NULL;
+	}
+
 	return left;
 }
 
-- 
2.51.0.568.g6b54b97edf
Previous: Jeff KingNext: Jeff King
Message 25 of 26 in “[BUG] git stash show -p with invalid option aborts with double-free in show_stash() (strvec_clear)”
  1. Lauri NiskanenSep 19, 2025
  2. Kristoffer HaugsbakkSep 19, 2025
  3. Junio C HamanoSep 19, 2025
  4. Jeff KingSep 19, 2025
  5. Junio C HamanoSep 19, 2025
  6. Junio C HamanoSep 19, 2025
  7. Jeff KingSep 19, 2025
  8. Junio C HamanoSep 19, 2025
  9. Jeff KingSep 19, 2025
  10. 0/6 fixing double-frees and leaks via setup_revisions()Jeff King, Sep 19, 2025
  11. 1/6 stash: tell setup_revisions() to free our allocated stringsJeff King, Sep 19, 2025
  12. Junio C HamanoSep 22, 2025
  13. Jeff KingSep 22, 2025
  14. Junio C HamanoSep 22, 2025
  15. Jeff KingSep 22, 2025
  16. Junio C HamanoSep 22, 2025
  17. Jeff KingSep 23, 2025
  18. 2/6 revision: manage memory ownership of argv in setup_revisions()Jeff King, Sep 19, 2025
  19. 3/6 revision: add wrapper to setup_revisions() from a strvecJeff King, Sep 19, 2025
  20. Eric SunshineSep 20, 2025
  21. Jeff KingSep 20, 2025
  22. 4/6 treewide: use setup_revisions_from_strvec() when we have a strvecJeff King, Sep 19, 2025
  23. 5/6 treewide: pass strvecs around for setup_revisions_from_strvec()Jeff King, Sep 19, 2025
  24. Jeff KingSep 19, 2025
  25. 6/6 revision: retain argv NULL invariant in setup_revisions()Jeff King, Sep 19, 2025
  26. Jeff KingSep 19, 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.