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

Re: [PATCH 7/7] determine_author_info: stop leaking name/email

From
Eric Sunshine <sunshine@sunshineco.com>
Date
Jun 23, 2014, 09:48 UTC
Message-ID
<CAPig+cRfTrUgJPV781zyV+m5gbYM9f2z+t=gfTU7grUDtX0mxA@mail.gmail.com>
In-Reply-To
<CABPQNSaqGaCnE7jY6yj_0m8iHpU2Y5rt9wAHW=sM_oH9r1qTzA@mail.gmail.com>
On Mon, Jun 23, 2014 at 5:33 AM, Erik Faye-Lund <kusmabite@gmail.com> wrote:
Show 91 quoted lines
> On Mon, Jun 23, 2014 at 11:28 AM, Eric Sunshine <sunshine@sunshineco.com> wrote:
>> On Wed, Jun 18, 2014 at 4:36 PM, Jeff King <peff@peff.net> wrote:
>>> When we get the author name and email either from an
>>> existing commit or from the "--author" option, we create a
>>> copy of the strings. We cannot just free() these copies,
>>> since the same pointers may also be pointing to getenv()
>>> storage which we do not own.
>>>
>>> Instead, let's treat these the same way as we do the date
>>> buffer: keep a strbuf to be released, and point the bare
>>> pointers at the strbuf.
>>>
>>> Signed-off-by: Jeff King <peff@peff.net>
>>> ---
>>>  builtin/commit.c | 20 +++++++++++++-------
>>>  1 file changed, 13 insertions(+), 7 deletions(-)
>>>
>>> diff --git a/builtin/commit.c b/builtin/commit.c
>>> index 62abee0..72beb7f 100644
>>> --- a/builtin/commit.c
>>> +++ b/builtin/commit.c
>>> @@ -546,16 +546,20 @@ static void strbuf_add_pair(struct strbuf *buf, const struct pointer_pair *p)
>>>         strbuf_add(buf, p->begin, p->end - p->begin);
>>>  }
>>>
>>> -static char *xmemdupz_pair(const struct pointer_pair *p)
>>> +static char *set_pair(struct strbuf *buf, struct pointer_pair *p)
>>>  {
>>> -       return xmemdupz(p->begin, p->end - p->begin);
>>> +       strbuf_reset(buf);
>>> +       strbuf_add_pair(buf, p);
>>> +       return buf->buf;
>>>  }
>>>
>>>  static void determine_author_info(struct strbuf *author_ident)
>>>  {
>>>         char *name, *email, *date;
>>>         struct ident_split author;
>>> -       struct strbuf date_buf = STRBUF_INIT;
>>> +       struct strbuf name_buf = STRBUF_INIT,
>>> +                     mail_buf = STRBUF_INIT,
>>
>> nit: The associated 'char *' variable is named "email", so perhaps
>> s/mail_buf/email_buf/g
>>
>>> +                     date_buf = STRBUF_INIT;
>>>
>>>         name = getenv("GIT_AUTHOR_NAME");
>>>         email = getenv("GIT_AUTHOR_EMAIL");
>>> @@ -572,8 +576,8 @@ static void determine_author_info(struct strbuf *author_ident)
>>>                 if (split_ident_line(&ident, a, len) < 0)
>>>                         die(_("commit '%s' has malformed author line"), author_message);
>>>
>>> -               name = xmemdupz_pair(&ident.name);
>>> -               email = xmemdupz_pair(&ident.mail);
>>> +               name = set_pair(&name_buf, &ident.name);
>>> +               email = set_pair(&mail_buf, &ident.mail);
>>>                 if (ident.date.begin) {
>>>                         strbuf_reset(&date_buf);
>>>                         strbuf_addch(&date_buf, '@');
>>> @@ -589,8 +593,8 @@ static void determine_author_info(struct strbuf *author_ident)
>>>
>>>                 if (split_ident_line(&ident, force_author, strlen(force_author)) < 0)
>>>                         die(_("malformed --author parameter"));
>>> -               name = xmemdupz_pair(&ident.name);
>>> -               email = xmemdupz_pair(&ident.mail);
>>> +               name = set_pair(&name_buf, &ident.name);
>>> +               email = set_pair(&mail_buf, &ident.mail);
>>
>> Does the code become too convoluted with these changes? You're now
>> maintaining three 'char *' variables in parallel with three strbuf
>> variables. Is it possible to drop the 'char *' variables and just pass
>> the .buf member of the strbufs to fmt_ident()?
>>
>> Alternately, you also could solve the leaks by having an envdup() helper:
>>
>>     static char *envdup(const char *s)
>>     {
>>         const char *v = getenv(s);
>>         return v ? xstrdup(v) : NULL;
>>     }
>>
>>     ...
>>     name = envdup("GIT_AUTHOR_NAME");
>>     email = envdup("GIT_AUTHOR_EMAIL");
>>     ...
>>
>> And then just free() 'name' and 'email' normally.
>
> This approach has the added benefit of fixing the case where getenv
> uses a static buffer, like POSIX allows.

That reminds me that I was going to suggest a suitable variation of envdup if Peff wanted to keep the strbufs:

    static void strbuf_env(struct strbuf *s, const char *e)
    {
        const char *v = getenv(e);
        if (v)
            strbuf_add(s, v);
    }

(Or add a generalized strbuf_add_gently() to strbuf.{h,c}, if it seems likely to come up more often, which would allow strbuf_add_gently(&name_buf, getenv("GIT_AUTHOR_NAME")) -- with a better name than "gently", of course.)

Previous: Erik Faye-LundNext: Jeff King
Message 14 of 16 in “cleaning up determine_author_info”
  1. 0/7 cleaning up determine_author_infoJeff King, Jun 18, 2014
  2. 1/7 commit: provide a function to find a header in a bufferJeff King, Jun 18, 2014
  3. Eric SunshineJun 23, 2014
  4. Jeff KingJun 23, 2014
  5. 2/7 record_author_info: fix memory leak on malformed commitJeff King, Jun 18, 2014
  6. 3/7 record_author_info: use find_commit_headerJeff King, Jun 18, 2014
  7. 4/7 ident_split: store begin/end pairs on their own structJeff King, Jun 18, 2014
  8. Eric SunshineJun 23, 2014
  9. 5/7 use strbufs in date functionsJeff King, Jun 18, 2014
  10. 6/7 determine_author_info: reuse parsing functionsJeff King, Jun 18, 2014
  11. 7/7 determine_author_info: stop leaking name/emailJeff King, Jun 18, 2014
  12. Eric SunshineJun 23, 2014
  13. Erik Faye-LundJun 23, 2014
  14. Eric SunshineJun 23, 2014
  15. Jeff KingJun 23, 2014
  16. Jeff KingJun 23, 2014

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.