Re: [PATCH 1/2] sequencer: stop exporting GIT_REFLOG_ACTION
- From
- Phillip Wood <phillip.wood123@gmail.com>
- Date
- Nov 7, 2022, 19:35 UTC
- Message-ID
- <03cd4cdb-5f6b-11b9-1959-d58d5b544565@dunelm.org.uk>
- In-Reply-To
- <221107.86iljqvhzf.gmgdl@evledraar.gmail.com>
Hi Ævar
On 07/11/2022 16:12, Ævar Arnfjörð Bjarmason wrote:
Show 19 quoted lines
>
> On Fri, Nov 04 2022, Phillip Wood via GitGitGadget wrote:
>
>> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
>> +static const char *sequencer_reflog_action(struct replay_opts *opts)
>> +{
>> + if (!opts->reflog_action) {
>> + opts->reflog_action = getenv(GIT_REFLOG_ACTION);
>> + opts->reflog_action =
>> + xstrdup(opts->reflog_action ? opts->reflog_action
>> + : action_name(opts));
>> + }
>> +
>> + return opts->reflog_action;
>> +}
>
> We always return an xstrdup'd here, so this should be a "char *" return
> value, not a "const char *"., butWe always return the same string, it is only allocated on the first call. opt->reflog_action is freed at the end of the rebase in sequencer_remove_state().
Show 54 quoted lines
>> __attribute__((format (printf, 3, 4)))
>> static const char *reflog_message(struct replay_opts *opts,
>> const char *sub_action, const char *fmt, ...)
>> {
>> va_list ap;
>> static struct strbuf buf = STRBUF_INIT;
>> - char *reflog_action = getenv(GIT_REFLOG_ACTION);
>>
>> va_start(ap, fmt);
>> strbuf_reset(&buf);
>
> Here we just reset the strbuf...
>
>> - strbuf_addstr(&buf, reflog_action ? reflog_action : action_name(opts));
>> + strbuf_addstr(&buf, sequencer_reflog_action(opts));
>
> Here we leak the freshly xstrdup'd value, mostly untested, but shouldn't
> this instead be:
>
> diff --git a/sequencer.c b/sequencer.c
> index e23f6f0b718..58a97e04c67 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -3695,10 +3695,11 @@ static const char *reflog_message(struct replay_opts *opts,
> {
> va_list ap;
> static struct strbuf buf = STRBUF_INIT;
> + char *msg = sequencer_reflog_action(opts);
>
> va_start(ap, fmt);
> strbuf_reset(&buf);
> - strbuf_addstr(&buf, sequencer_reflog_action(opts));
> + strbuf_attach(&buf, msg, strlen(msg), strlen(msg) + 1);
> if (sub_action)
> strbuf_addf(&buf, " (%s)", sub_action);
> if (fmt) {
>
> Of course that requires dropping the "const", per the above...
>
>
>> if (sub_action)
>> strbuf_addf(&buf, " (%s)", sub_action);
>> if (fmt) {
>> @@ -4497,7 +4511,7 @@ static int checkout_onto(struct repository *r, struct replay_opts *opts,
>> RESET_HEAD_RUN_POST_CHECKOUT_HOOK,
>> .head_msg = reflog_message(opts, "start", "checkout %s",
>> onto_name),
>> - .default_reflog_action = "rebase"
>> + .default_reflog_action = sequencer_reflog_action(opts)
>
> Here we'd before hand a fixed string to reset_head(), but now it's
> xstrdup()'d, but the corresponding free() on that side is missing.
>
> But aren't we always just returing "rebase" here still?Yes but I think it makes sense to call squencer_reflog_action() in case this changes in the future. Note I don't think this is leaking anything.
Show 12 quoted lines
>> [...] >> @@ -5116,7 +5121,7 @@ static int single_pick(struct repository *r, >> TODO_PICK : TODO_REVERT; >> item.commit = cmit; >> >> - setenv(GIT_REFLOG_ACTION, action_name(opts), 0); >> + opts->reflog_message = sequencer_reflog_action(opts); >> return do_pick_commit(r, &item, opts, 0, &check_todo); > > Here you're adding a new memory leak, which you can see if you run > e.g. the 1st test of ./t1013-read-tree-submodule.sh before & after this > change.
I'm not sure how, opts->reflog_message will be a copy of opts->reflog_action which is freed at the end of the rebase. I'll have a proper look tomorrow to see if I'm missing something.
Best Wishes
Phillip