diff mbox series

[12/23] builtin/rev-parse: fix memory leak with `--parseopt`

Message ID e277222bd298560b0d7f10cb9b5d0eee5967ba87.1721995576.git.ps@pks.im (mailing list archive)
State Superseded
Headers show
Series Memory leak fixes (pt.3) | expand

Commit Message

Patrick Steinhardt July 26, 2024, 12:16 p.m. UTC
The `--parseopt` mode allows shell scripts to have the same option
parsing mode as we have in C builtins. It soaks up a set of option
descriptions via stdin and massages them into proper `struct option`s
that we can then use to parse a set of arguments.

We only partially free those options when done though, creating a memory
leak. Interestingly, we only end up free'ing the first option's help,
which is of course wrong.

Fix this by freeing all option's help fields as well as their `argh`
fielids to plug this memory leak.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/rev-parse.c           | 5 ++++-
 t/t1502-rev-parse-parseopt.sh | 2 ++
 2 files changed, 6 insertions(+), 1 deletion(-)

Comments

karthik nayak July 30, 2024, 11 a.m. UTC | #1
Patrick Steinhardt <ps@pks.im> writes:

> The `--parseopt` mode allows shell scripts to have the same option
> parsing mode as we have in C builtins. It soaks up a set of option
> descriptions via stdin and massages them into proper `struct option`s
> that we can then use to parse a set of arguments.
>
> We only partially free those options when done though, creating a memory
> leak. Interestingly, we only end up free'ing the first option's help,
> which is of course wrong.
>
> Fix this by freeing all option's help fields as well as their `argh`
> fielids to plug this memory leak.
>

s/fielids/fields

[snip]
diff mbox series

Patch

diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 2e64f5bda7..5845d3f59b 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -553,7 +553,10 @@  static int cmd_parseopt(int argc, const char **argv, const char *prefix)
 	strbuf_release(&sb);
 	strvec_clear(&longnames);
 	strvec_clear(&usage);
-	free((char *) opts->help);
+	for (size_t i = 0; i < opts_nr; i++) {
+		free((char *) opts[i].help);
+		free((char *) opts[i].argh);
+	}
 	free(opts);
 	return 0;
 }
diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh
index b754b9fd74..5eaa6428c4 100755
--- a/t/t1502-rev-parse-parseopt.sh
+++ b/t/t1502-rev-parse-parseopt.sh
@@ -1,6 +1,8 @@ 
 #!/bin/sh
 
 test_description='test git rev-parse --parseopt'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 check_invalid_long_option () {