Git fork

stash: tell setup_revisions() to free our allocated strings

In "git stash show", we do a first pass of parsing our command line
options by splitting them into revision args and stash args. These are
stored in strvecs, and we pass the revision args to setup_revisions().

But setup_revisions() may modify the argv we pass it, causing us to leak
some of the entries. In particular, if it sees a "--" string, that will
be dropped from argv. This is the same as other cases addressed by
f92dbdbc6a (revisions API: don't leak memory on argv elements that need
free()-ing, 2022-08-02), and we should fix it the same way: by passing
the free_removed_argv_elements option to setup_revisions().

The added test here is run only with SANITIZE=leak, without checking its
output, because the behavior of stash with "--" is a little odd:

1. Running "git stash show" will show --stat output. But running "git
stash show --" will show --patch.

2. I'd expect a non-option after "--" to be treated as a pathspec, so:

git stash show -p 1 -- foo

would look treat "1" as a stash (a synonym for stash@{1}) and
restrict the resulting diff to "foo". But it doesn't. We split the
revision/stash args without any regard to "--". So in the example
above both "1" and "foo" are stashes. Which is an error, but also:

git stash show -- foo

treats "foo" as a stash, not a pathspec.

These are both oddities that we may want to address (or may not, if we
want to retain historical quirks). But they are well outside the scope
of this patch. So for now we'll just let the tests confirm we aren't
leaking without otherwise expecting any behavior. If we later address
either of those points and end up with another test that covers "stash
show --", we can drop this leak-only test.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

Jeff King and committed by
Junio C Hamano
3ea35c64 c44beea4

+6 -1
+2 -1
builtin/stash.c
··· 956 956 static int show_stash(int argc, const char **argv, const char *prefix, 957 957 struct repository *repo UNUSED) 958 958 { 959 + struct setup_revision_opt opt = { .free_removed_argv_elements = 1 }; 959 960 int i; 960 961 int ret = -1; 961 962 struct stash_info info = STASH_INFO_INIT; ··· 1014 1015 } 1015 1016 } 1016 1017 1017 - argc = setup_revisions(revision_args.nr, revision_args.v, &rev, NULL); 1018 + argc = setup_revisions(revision_args.nr, revision_args.v, &rev, &opt); 1018 1019 if (argc > 1) 1019 1020 goto usage; 1020 1021 if (!rev.diffopt.output_format) {
+4
t/t3903-stash.sh
··· 1741 1741 ) 1742 1742 ' 1743 1743 1744 + test_expect_success SANITIZE_LEAK 'stash show handles -- without leaking' ' 1745 + git stash show -- 1746 + ' 1747 + 1744 1748 test_done