All of lore.kernel.org
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: Jeff King <peff@peff.net>
Cc: Eric Sunshine <sunshine@sunshineco.com>,
	Stefan Beller <sbeller@google.com>,
	Git List <git@vger.kernel.org>
Subject: Re: [PATCH 4/6] abbrev_sha1_in_line: don't leak memory
Date: Wed, 30 Mar 2016 10:06:41 -0700	[thread overview]
Message-ID: <xmqqzitfuc7y.fsf@gitster.mtv.corp.google.com> (raw)
In-Reply-To: <20160330013127.GA6680@sigill.intra.peff.net> (Jeff King's message of "Tue, 29 Mar 2016 21:31:28 -0400")

Jeff King <peff@peff.net> writes:

> On Tue, Mar 29, 2016 at 09:30:38PM -0400, Eric Sunshine wrote:
>
>> The implementation of strbuf_list_free() is this:
>> 
>>     struct strbuf **s = sbs;
>>     while (*s) {
>>         strbuf_release(*s);
>>         free(*s++);
>>     }
>>     free(sbs);
>> 
>> which means that wt-status.c is leaking not only 'split', but also
>> each element of split[], right?
>
> Yeah, I didn't notice that, but I think you're right.

Correct.

I suspect that we would be better off in the longer term if
we made conscious effort to deprecate and eradicate the use
of strbuf_split* API functions.  They are easy to write
crappy code with, inefficient, and error prone.  You would
rarely need to have N resulting pieces as strbufs to be
easily manipulatable [*1*].

The function can be written by not using the "split and then
rebuild" pattern, perhaps like so, and the result is even
easier to read and understand, I would say.  A sample rewrite
is attached at the end.


[Footnote]

*1* I wouldn't be this harsh if the function were to fill an
    array of pointers or offsets into the original string.

 wt-status.c | 43 +++++++++++++++++++------------------------
 1 file changed, 19 insertions(+), 24 deletions(-)

diff --git a/wt-status.c b/wt-status.c
index ef74864..4886c35 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -1037,35 +1037,30 @@ static int split_commit_in_progress(struct wt_status *s)
  */
 static void abbrev_sha1_in_line(struct strbuf *line)
 {
-	struct strbuf **split;
-	int i;
+	const char *cp, *ep, *abbrev;
+	unsigned char sha1[20];
 
-	if (starts_with(line->buf, "exec ") ||
-	    starts_with(line->buf, "x "))
+	/* the oddball "exec" does not have 40-hex as the second token */
+	if (starts_with(line->buf, "exec ") || starts_with(line->buf, "x "))
 		return;
 
-	split = strbuf_split_max(line, ' ', 3);
-	if (split[0] && split[1]) {
-		unsigned char sha1[20];
-		const char *abbrev;
+	/* find the second token on the line */
+	cp = strchr(line->buf, ' ');
+	if (!cp)
+		return;
+	cp++;
+	ep = strchr(cp, ' ');
+	if (!ep)
+		return;
 
-		/*
-		 * strbuf_split_max left a space. Trim it and re-add
-		 * it after abbreviation.
-		 */
-		strbuf_trim(split[1]);
-		if (!get_sha1(split[1]->buf, sha1)) {
-			abbrev = find_unique_abbrev(sha1, DEFAULT_ABBREV);
-			strbuf_reset(split[1]);
-			strbuf_addf(split[1], "%s ", abbrev);
-			strbuf_reset(line);
-			for (i = 0; split[i]; i++)
-				strbuf_addf(line, "%s", split[i]->buf);
-		}
-	}
-	for (i = 0; split[i]; i++)
-		strbuf_release(split[i]);
+	/* is it 40-hex? */
+	if (ep - cp != GIT_SHA1_HEXSZ || get_sha1_hex(cp, sha1))
+		return;
 
+	/* replace it with its abbreviation */
+	abbrev = find_unique_abbrev(sha1, DEFAULT_ABBREV);
+	strbuf_splice(line, cp - line->buf, GIT_SHA1_HEXSZ,
+		      abbrev, strlen(abbrev));
 }
 
 static void read_rebase_todolist(const char *fname, struct string_list *lines)

  reply	other threads:[~2016-03-30 17:06 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-30  0:38 [PATCH 0/6] Some cleanups Stefan Beller
2016-03-30  0:38 ` [PATCH 1/6] path.c: allocate enough memory for string Stefan Beller
2016-03-30  0:56   ` Junio C Hamano
2016-03-30  0:57   ` Eric Sunshine
2016-03-30 16:41     ` Stefan Beller
2016-03-30 17:16       ` Junio C Hamano
2016-03-30  0:38 ` [PATCH 2/6] imap-send.c, cram: allocate enough memory for null terminated string Stefan Beller
2016-03-30  1:02   ` Eric Sunshine
2016-03-30  1:07   ` Jeff King
2016-03-30  0:38 ` [PATCH 3/6] notes: don't leak memory in git_config_get_notes_strategy Stefan Beller
2016-03-30  1:11   ` Eric Sunshine
2016-03-30  1:13   ` Jeff King
2016-03-30 17:17     ` Junio C Hamano
2016-03-30  0:38 ` [PATCH 4/6] abbrev_sha1_in_line: don't leak memory Stefan Beller
2016-03-30  1:11   ` Jeff King
2016-03-30  1:30     ` Eric Sunshine
2016-03-30  1:31       ` Jeff King
2016-03-30 17:06         ` Junio C Hamano [this message]
2016-03-30 17:21           ` Jeff King
2016-03-30  0:38 ` [PATCH 5/6] bundle: don't leak an fd in case of early return Stefan Beller
2016-03-30  1:17   ` Jeff King
2016-03-30 17:19     ` Junio C Hamano
2016-03-30  0:38 ` [PATCH 6/6] credential-cache, send_request: close fd when done Stefan Beller
2016-03-30  1:20   ` Jeff King

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=xmqqzitfuc7y.fsf@gitster.mtv.corp.google.com \
    --to=gitster@pobox.com \
    --cc=git@vger.kernel.org \
    --cc=peff@peff.net \
    --cc=sbeller@google.com \
    --cc=sunshine@sunshineco.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.