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

Re: [PATCH] mailinfo: fix out-of-bounds memory reads in unquote_quoted_pair()

From
Jeff King <peff@peff.net>
Date
Dec 13, 2023, 08:20 UTC
Message-ID
<20231213082027.GB1684525@coredump.intra.peff.net>
In-Reply-To
<ZXlYIZ0Hb1kN84NU@tanuki>
On Wed, Dec 13, 2023 at 08:07:21AM +0100, Patrick Steinhardt wrote:
Show 17 quoted lines
> >  static const char *unquote_quoted_string(struct strbuf *outbuf, const char *in)
> >  {
> > -	int c;
> >  	int take_next_literally = 0;
> >  
> > -	while ((c = *in++) != 0) {
> > +	while (*in) {
> > +		int c = *in++;
> >  		if (take_next_literally == 1) {
> >  			take_next_literally = 0;
> >  		} else {
> 
> I was wondering whether we want to convert `unquote_quoted_pair()` in
> the same way. It's not subject to the same issue because it doesn't
> return `in` to its callers. But it would lower the cognitive overhead a
> bit by keeping the coding style consistent. But please feel free to
> ignore this remark.

I dunno. I don't think the consistency matters that much between functions, and on its own, the "while ((c = *in++))" pattern is not harmful. It's used elsewhere in the same file for other functions that are also fine (for decoding q/b headers).

Show 8 quoted lines
> Another thing I was wondering about is the recursive nature of these
> functions, and whether it can lead to similar issues like we recently
> had when parsing revisions with stack exhaustion. I _think_ this should
> not be much of a problem in this case though, as we're talking about
> mail headers here. While the length of header values isn't restricted
> per se (the line length is restricted to 1000, but with Comment Folding
> Whitespace values can span multiple lines), but mail provdiers will sure
> clamp down on mails with a "From:" header that is megabytes in size.

It's just unquote_comment() that is recursive, but yeah, there is nothing to stop it from recursing forever on "((((((...". The stack requirements are pretty small, though. I needed between 2^17 and 2^18 bytes to segfault on my machine using:

  perl -e 'print "From: ", "(" x 2**18;' |
  git mailinfo /dev/null /dev/null

Absurdly big for an email, but maybe within the realm of possibility? I think it might be possible to drop the recursion and just use a depth counter, like this:

diff --git a/mailinfo.c b/mailinfo.c
index 737b9e5e13..db236f9f9f 100644
--- a/mailinfo.c
+++ b/mailinfo.c
@@ -59,6 +59,7 @@ static void parse_bogus_from(struct mailinfo *mi, const struct strbuf *line)
 static const char *unquote_comment(struct strbuf *outbuf, const char *in)
 {
 	int take_next_literally = 0;
+	int depth = 1;
 
 	strbuf_addch(outbuf, '(');
 
@@ -72,11 +73,14 @@ static const char *unquote_comment(struct strbuf *outbuf, const char *in)
 				take_next_literally = 1;
 				continue;
 			case '(':
-				in = unquote_comment(outbuf, in);
+				strbuf_addch(outbuf, '(');
+				depth++;
 				continue;
 			case ')':
 				strbuf_addch(outbuf, ')');
-				return in;
+				if (!--depth)
+					return in;
+				continue;
 			}
 		}
 
I doubt it's a big deal either way, but if it's that easy to do it might
be worth it.

-Peff
Previous: Patrick SteinhardtNext: Patrick Steinhardt
Message 3 of 10 in “mailinfo: fix out-of-bounds memory reads in unquote_quoted_pair()”
  1. mailinfo: fix out-of-bounds memory reads in unquote_quoted_pair()Jeff King, Dec 12, 2023
  2. Patrick SteinhardtDec 13, 2023
  3. Jeff KingDec 13, 2023
  4. Patrick SteinhardtDec 14, 2023
  5. 0/2 avoiding recursion in mailinfoJeff King, Dec 14, 2023
  6. 1/2 t5100: make rfc822 comment test more carefulJeff King, Dec 14, 2023
  7. 2/2 mailinfo: avoid recursion when unquoting From headersJeff King, Dec 14, 2023
  8. Patrick SteinhardtDec 15, 2023
  9. Junio C HamanoDec 13, 2023
  10. Jeff KingDec 14, 2023

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.