mailinfo: fix pointential memory leak if decode_header failed

In mailinfo.c:decode_header, if convert_to_utf8 failed, the strbuf stored
in dec will leak. Simply add strbuf_release and free(dec) will solve
this problem.

Signed-off-by: Lidong Yan <502024330056@smail.nju.edu.cn>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Lidong Yan
2025-05-13 02:49:10 +00:00
committed by Junio C Hamano
parent 1a8a4971cc
commit 56f1cd10f4

View File

@@ -381,12 +381,12 @@ static int is_format_patch_separator(const char *line, int len)
return !memcmp(SAMPLE + (cp - line), cp, strlen(SAMPLE) - (cp - line)); return !memcmp(SAMPLE + (cp - line), cp, strlen(SAMPLE) - (cp - line));
} }
static struct strbuf *decode_q_segment(const struct strbuf *q_seg, int rfc2047) static int decode_q_segment(struct strbuf *out, const struct strbuf *q_seg,
int rfc2047)
{ {
const char *in = q_seg->buf; const char *in = q_seg->buf;
int c; int c;
struct strbuf *out = xmalloc(sizeof(struct strbuf)); strbuf_grow(out, q_seg->len);
strbuf_init(out, q_seg->len);
while ((c = *in++) != 0) { while ((c = *in++) != 0) {
if (c == '=') { if (c == '=') {
@@ -405,16 +405,15 @@ static struct strbuf *decode_q_segment(const struct strbuf *q_seg, int rfc2047)
c = 0x20; c = 0x20;
strbuf_addch(out, c); strbuf_addch(out, c);
} }
return out; return 0;
} }
static struct strbuf *decode_b_segment(const struct strbuf *b_seg) static int decode_b_segment(struct strbuf *out, const struct strbuf *b_seg)
{ {
/* Decode in..ep, possibly in-place to ot */ /* Decode in..ep, possibly in-place to ot */
int c, pos = 0, acc = 0; int c, pos = 0, acc = 0;
const char *in = b_seg->buf; const char *in = b_seg->buf;
struct strbuf *out = xmalloc(sizeof(struct strbuf)); strbuf_grow(out, b_seg->len);
strbuf_init(out, b_seg->len);
while ((c = *in++) != 0) { while ((c = *in++) != 0) {
if (c == '+') if (c == '+')
@@ -447,7 +446,7 @@ static struct strbuf *decode_b_segment(const struct strbuf *b_seg)
break; break;
} }
} }
return out; return 0;
} }
static int convert_to_utf8(struct mailinfo *mi, static int convert_to_utf8(struct mailinfo *mi,
@@ -475,7 +474,7 @@ static int convert_to_utf8(struct mailinfo *mi,
static void decode_header(struct mailinfo *mi, struct strbuf *it) static void decode_header(struct mailinfo *mi, struct strbuf *it)
{ {
char *in, *ep, *cp; char *in, *ep, *cp;
struct strbuf outbuf = STRBUF_INIT, *dec; struct strbuf outbuf = STRBUF_INIT, dec = STRBUF_INIT;
struct strbuf charset_q = STRBUF_INIT, piecebuf = STRBUF_INIT; struct strbuf charset_q = STRBUF_INIT, piecebuf = STRBUF_INIT;
int found_error = 1; /* pessimism */ int found_error = 1; /* pessimism */
@@ -530,18 +529,19 @@ static void decode_header(struct mailinfo *mi, struct strbuf *it)
default: default:
goto release_return; goto release_return;
case 'b': case 'b':
dec = decode_b_segment(&piecebuf); if ((found_error = decode_b_segment(&dec, &piecebuf)))
goto release_return;
break; break;
case 'q': case 'q':
dec = decode_q_segment(&piecebuf, 1); if ((found_error = decode_q_segment(&dec, &piecebuf, 1)))
goto release_return;
break; break;
} }
if (convert_to_utf8(mi, dec, charset_q.buf)) if (convert_to_utf8(mi, &dec, charset_q.buf))
goto release_return; goto release_return;
strbuf_addbuf(&outbuf, dec); strbuf_addbuf(&outbuf, &dec);
strbuf_release(dec); strbuf_release(&dec);
free(dec);
in = ep + 2; in = ep + 2;
} }
strbuf_addstr(&outbuf, in); strbuf_addstr(&outbuf, in);
@@ -552,6 +552,7 @@ release_return:
strbuf_release(&outbuf); strbuf_release(&outbuf);
strbuf_release(&charset_q); strbuf_release(&charset_q);
strbuf_release(&piecebuf); strbuf_release(&piecebuf);
strbuf_release(&dec);
if (found_error) if (found_error)
mi->input_error = -1; mi->input_error = -1;
@@ -634,23 +635,22 @@ static int is_inbody_header(const struct mailinfo *mi,
static void decode_transfer_encoding(struct mailinfo *mi, struct strbuf *line) static void decode_transfer_encoding(struct mailinfo *mi, struct strbuf *line)
{ {
struct strbuf *ret; struct strbuf ret = STRBUF_INIT;
switch (mi->transfer_encoding) { switch (mi->transfer_encoding) {
case TE_QP: case TE_QP:
ret = decode_q_segment(line, 0); decode_q_segment(&ret, line, 0);
break; break;
case TE_BASE64: case TE_BASE64:
ret = decode_b_segment(line); decode_b_segment(&ret, line);
break; break;
case TE_DONTCARE: case TE_DONTCARE:
default: default:
return; return;
} }
strbuf_reset(line); strbuf_reset(line);
strbuf_addbuf(line, ret); strbuf_addbuf(line, &ret);
strbuf_release(ret); strbuf_release(&ret);
free(ret);
} }
static inline int patchbreak(const struct strbuf *line) static inline int patchbreak(const struct strbuf *line)