* [PATCH] show-branch: use strbuf instead of static buffer
@ 2013-04-05 21:15 Jeff King
2013-04-05 23:49 ` Jonathan Nieder
0 siblings, 1 reply; 3+ messages in thread
From: Jeff King @ 2013-04-05 21:15 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Eric Roman, git
When we generate relative names (e.g., "master~20^2"), we
format the name into a static buffer, then xstrdup the
result to attach it to the commit. Since the first thing we
add into the static buffer is the already-computed name of
the child commit, the names may get longer and longer as
the traversal gets deeper, and we may eventually overflow
the fixed-size buffer.
Fix this by converting the fixed-size buffer into a dynamic
strbuf. The performance implications should be minimal, as
we end up allocating a heap copy of the name anyway (and now
we can just detach the heap copy from the strbuf).
Reported-by: Eric Roman <eroman@chromium.org>
Signed-off-by: Jeff King <peff@peff.net>
---
This is a fix for a bug report that came to me off-list. A real-world
example can be seen by running "git show-branch --all" on a fresh clone
of:
https://chromium.googlesource.com/chromium/src.git
(but that repo is 1.7G, so I don't recommend cloning it unless you're
really interested). Its master branch consists of a strange sequence of
merges that results in naming commits like master^2^2^2^2... and so on
(it's unclear to me why, but it looks like maybe syncing up separate svn
and git repositories?). Which is odd, but looking at graph, I think the
names show-branch is generating are correct; they're just really long.
And of course odd history is no excuse to overflow a buffer.
Though this is a stack overflow, I don't know that it's exploitable for
anything interesting; an attacker does not get to write arbitrary data,
but rather only a sequence of "^%d" and "~%d" relative history markers.
Perhaps in theory one could devise a history such that the sequence
markers spelled out some malicious code, but it would be quite a
challenge (and given that you have only ascii [^~0-9] to work with,
probably impossible).
I prepared this on "master", but it should be suitable for "maint"; the
code dates all the way back to git v0.99.
builtin/show-branch.c | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index d208fd6..90fc6b1 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -162,29 +162,28 @@ static void name_commits(struct commit_list *list,
nth = 0;
while (parents) {
struct commit *p = parents->item;
- char newname[1000], *en;
+ struct strbuf newname = STRBUF_INIT;
parents = parents->next;
nth++;
if (p->util)
continue;
- en = newname;
switch (n->generation) {
case 0:
- en += sprintf(en, "%s", n->head_name);
+ strbuf_addstr(&newname, n->head_name);
break;
case 1:
- en += sprintf(en, "%s^", n->head_name);
+ strbuf_addf(&newname, "%s^", n->head_name);
break;
default:
- en += sprintf(en, "%s~%d",
- n->head_name, n->generation);
+ strbuf_addf(&newname, "%s~%d",
+ n->head_name, n->generation);
break;
}
if (nth == 1)
- en += sprintf(en, "^");
+ strbuf_addch(&newname, '^');
else
- en += sprintf(en, "^%d", nth);
- name_commit(p, xstrdup(newname), 0);
+ strbuf_addf(&newname, "^%d", nth);
+ name_commit(p, strbuf_detach(&newname, NULL), 0);
i++;
name_first_parent_chain(p);
}
--
1.8.2.rc0.33.gd915649
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] show-branch: use strbuf instead of static buffer
2013-04-05 21:15 [PATCH] show-branch: use strbuf instead of static buffer Jeff King
@ 2013-04-05 23:49 ` Jonathan Nieder
2013-04-06 4:58 ` Jeff King
0 siblings, 1 reply; 3+ messages in thread
From: Jonathan Nieder @ 2013-04-05 23:49 UTC (permalink / raw)
To: Jeff King; +Cc: Junio C Hamano, Eric Roman, git
Jeff King wrote:
> When we generate relative names (e.g., "master~20^2"), we
> format the name into a static buffer, then xstrdup the
> result to attach it to the commit. Since the first thing we
> add into the static buffer is the already-computed name of
> the child commit, the names may get longer and longer as
> the traversal gets deeper, and we may eventually overflow
> the fixed-size buffer.
Good catch.
[...]
> Though this is a stack overflow, I don't know that it's exploitable for
> anything interesting; an attacker does not get to write arbitrary data,
> but rather only a sequence of "^%d" and "~%d" relative history markers.
> Perhaps in theory one could devise a history such that the sequence
> markers spelled out some malicious code, but it would be quite a
> challenge
Overwrite the return address and return-to-libc?
[...]
> --- a/builtin/show-branch.c
> +++ b/builtin/show-branch.c
Very clean and obviously correct. Thanks.
Reviewed-by: Jonathan Nieder <jrnieder@gmail.com>
A test would be nice, though.
Hope that helps,
Jonathan
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] show-branch: use strbuf instead of static buffer
2013-04-05 23:49 ` Jonathan Nieder
@ 2013-04-06 4:58 ` Jeff King
0 siblings, 0 replies; 3+ messages in thread
From: Jeff King @ 2013-04-06 4:58 UTC (permalink / raw)
To: Jonathan Nieder; +Cc: Junio C Hamano, Eric Roman, git
On Fri, Apr 05, 2013 at 04:49:15PM -0700, Jonathan Nieder wrote:
> > Though this is a stack overflow, I don't know that it's exploitable for
> > anything interesting; an attacker does not get to write arbitrary data,
> > but rather only a sequence of "^%d" and "~%d" relative history markers.
> > Perhaps in theory one could devise a history such that the sequence
> > markers spelled out some malicious code, but it would be quite a
> > challenge
>
> Overwrite the return address and return-to-libc?
Still hard, since you need to construct a usable address (and arguments)
out of sequences of "^[0-9]+" and "~[0-9]+". But I'd love to see a
working exploit if somebody thinks they can do it. :)
> Very clean and obviously correct. Thanks.
>
> Reviewed-by: Jonathan Nieder <jrnieder@gmail.com>
Thanks.
> A test would be nice, though.
What should it be testing? That a giant chain of second-parent merges
that exceeds 1000 bytes doesn't segfault? Tests like that are not all
that interesting, because they do not catch real-world regressions. We
have closed this barn door; it is not impossible that it will be
re-opened, but it is not likely. A test that checks only for a very
specific type of failure is only ever going to see that failure.
If you want to design a suite of tests that check that show-branch gives
correct output for particular brands of large repo, that would be
generic and potentially useful. But I don't think it's actually worth
spending a lot of time on (reviewing the code for more static buffers
and sprintfs would probably be a much more fruitful use of time).
-Peff
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2013-04-06 16:59 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-05 21:15 [PATCH] show-branch: use strbuf instead of static buffer Jeff King
2013-04-05 23:49 ` Jonathan Nieder
2013-04-06 4:58 ` Jeff King
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).