Skip to content

Commit dee1829

Browse files
peffgitster
authored andcommitted
mailinfo: avoid recursion when unquoting From headers
Our unquote_comment() function is recursive; when it sees a comment within a comment, like: (this is an (embedded) comment) it recurses to handle the inner comment. This is fine for practical use, but it does mean that you can easily run out of stack space with a malicious header. For example: perl -e 'print "From: ", "(" x 2**18;' | git mailinfo /dev/null /dev/null segfaults on my system. And since mailinfo is likely to be fed untrusted input from the Internet (if not by human users, who might recognize a garbage header, but certainly there are automated systems that apply patches from a list) it may be possible for an attacker to trigger the problem. That said, I don't think there's an interesting security vulnerability here. All an attacker can do is make it impossible to parse their email and apply their patch, and there are lots of ways to generate bogus emails. So it's more of an annoyance than anything. But it's pretty easy to fix it. The recursion is not helping us preserve any particular state from each level. The only flag in our parsing is take_next_literally, and we can never recurse when it is set (since the start of a new comment implies it was not backslash-escaped). So it is really only useful for finding the end of the matched pair of parentheses. We can do that easily with a simple depth counter. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 2d9396c commit dee1829

File tree

1 file changed

+6
-2
lines changed

1 file changed

+6
-2
lines changed

mailinfo.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ static void parse_bogus_from(struct mailinfo *mi, const struct strbuf *line)
5757
static const char *unquote_comment(struct strbuf *outbuf, const char *in)
5858
{
5959
int take_next_literally = 0;
60+
int depth = 1;
6061

6162
strbuf_addch(outbuf, '(');
6263

@@ -70,11 +71,14 @@ static const char *unquote_comment(struct strbuf *outbuf, const char *in)
7071
take_next_literally = 1;
7172
continue;
7273
case '(':
73-
in = unquote_comment(outbuf, in);
74+
strbuf_addch(outbuf, '(');
75+
depth++;
7476
continue;
7577
case ')':
7678
strbuf_addch(outbuf, ')');
77-
return in;
79+
if (!--depth)
80+
return in;
81+
continue;
7882
}
7983
}
8084

0 commit comments

Comments
 (0)