Skip to content

Commit 2426a21

Browse files
committed
Merge branch 'ly/mailinfo-decode-header-leakfix'
Leakfix. * ly/mailinfo-decode-header-leakfix: mailinfo: fix pointential memory leak if `decode_header` failed
2 parents dcb8974 + 56f1cd1 commit 2426a21

File tree

1 file changed

+21
-21
lines changed

1 file changed

+21
-21
lines changed

mailinfo.c

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -381,12 +381,12 @@ static int is_format_patch_separator(const char *line, int len)
381381
return !memcmp(SAMPLE + (cp - line), cp, strlen(SAMPLE) - (cp - line));
382382
}
383383

384-
static struct strbuf *decode_q_segment(const struct strbuf *q_seg, int rfc2047)
384+
static int decode_q_segment(struct strbuf *out, const struct strbuf *q_seg,
385+
int rfc2047)
385386
{
386387
const char *in = q_seg->buf;
387388
int c;
388-
struct strbuf *out = xmalloc(sizeof(struct strbuf));
389-
strbuf_init(out, q_seg->len);
389+
strbuf_grow(out, q_seg->len);
390390

391391
while ((c = *in++) != 0) {
392392
if (c == '=') {
@@ -405,16 +405,15 @@ static struct strbuf *decode_q_segment(const struct strbuf *q_seg, int rfc2047)
405405
c = 0x20;
406406
strbuf_addch(out, c);
407407
}
408-
return out;
408+
return 0;
409409
}
410410

411-
static struct strbuf *decode_b_segment(const struct strbuf *b_seg)
411+
static int decode_b_segment(struct strbuf *out, const struct strbuf *b_seg)
412412
{
413413
/* Decode in..ep, possibly in-place to ot */
414414
int c, pos = 0, acc = 0;
415415
const char *in = b_seg->buf;
416-
struct strbuf *out = xmalloc(sizeof(struct strbuf));
417-
strbuf_init(out, b_seg->len);
416+
strbuf_grow(out, b_seg->len);
418417

419418
while ((c = *in++) != 0) {
420419
if (c == '+')
@@ -447,7 +446,7 @@ static struct strbuf *decode_b_segment(const struct strbuf *b_seg)
447446
break;
448447
}
449448
}
450-
return out;
449+
return 0;
451450
}
452451

453452
static int convert_to_utf8(struct mailinfo *mi,
@@ -475,7 +474,7 @@ static int convert_to_utf8(struct mailinfo *mi,
475474
static void decode_header(struct mailinfo *mi, struct strbuf *it)
476475
{
477476
char *in, *ep, *cp;
478-
struct strbuf outbuf = STRBUF_INIT, *dec;
477+
struct strbuf outbuf = STRBUF_INIT, dec = STRBUF_INIT;
479478
struct strbuf charset_q = STRBUF_INIT, piecebuf = STRBUF_INIT;
480479
int found_error = 1; /* pessimism */
481480

@@ -530,18 +529,19 @@ static void decode_header(struct mailinfo *mi, struct strbuf *it)
530529
default:
531530
goto release_return;
532531
case 'b':
533-
dec = decode_b_segment(&piecebuf);
532+
if ((found_error = decode_b_segment(&dec, &piecebuf)))
533+
goto release_return;
534534
break;
535535
case 'q':
536-
dec = decode_q_segment(&piecebuf, 1);
536+
if ((found_error = decode_q_segment(&dec, &piecebuf, 1)))
537+
goto release_return;
537538
break;
538539
}
539-
if (convert_to_utf8(mi, dec, charset_q.buf))
540+
if (convert_to_utf8(mi, &dec, charset_q.buf))
540541
goto release_return;
541542

542-
strbuf_addbuf(&outbuf, dec);
543-
strbuf_release(dec);
544-
free(dec);
543+
strbuf_addbuf(&outbuf, &dec);
544+
strbuf_release(&dec);
545545
in = ep + 2;
546546
}
547547
strbuf_addstr(&outbuf, in);
@@ -552,6 +552,7 @@ static void decode_header(struct mailinfo *mi, struct strbuf *it)
552552
strbuf_release(&outbuf);
553553
strbuf_release(&charset_q);
554554
strbuf_release(&piecebuf);
555+
strbuf_release(&dec);
555556

556557
if (found_error)
557558
mi->input_error = -1;
@@ -634,23 +635,22 @@ static int is_inbody_header(const struct mailinfo *mi,
634635

635636
static void decode_transfer_encoding(struct mailinfo *mi, struct strbuf *line)
636637
{
637-
struct strbuf *ret;
638+
struct strbuf ret = STRBUF_INIT;
638639

639640
switch (mi->transfer_encoding) {
640641
case TE_QP:
641-
ret = decode_q_segment(line, 0);
642+
decode_q_segment(&ret, line, 0);
642643
break;
643644
case TE_BASE64:
644-
ret = decode_b_segment(line);
645+
decode_b_segment(&ret, line);
645646
break;
646647
case TE_DONTCARE:
647648
default:
648649
return;
649650
}
650651
strbuf_reset(line);
651-
strbuf_addbuf(line, ret);
652-
strbuf_release(ret);
653-
free(ret);
652+
strbuf_addbuf(line, &ret);
653+
strbuf_release(&ret);
654654
}
655655

656656
static inline int patchbreak(const struct strbuf *line)

0 commit comments

Comments
 (0)