On Fri, May 14, 2010 at 10:26:40AM -0400, Jeffrey Stedfast wrote:
> On 05/14/2010 05:19 AM, Damian Pietras wrote:
> > I've hit a bug in gmime 2.4.15 while composing a message. Gmime is
> > segfaulting if I use GMIME_CONTENT_ENCODING_QUOTEDPRINTABLE. Valgrind
> > says it's a buffer overflow while encoding to quoted printable.
> >
> > It's right, in a simple test case that encodes mostly binary data
> > using GMIME_CONTENT_ENCODING_QUOTEDPRINTABLE a buffer overrun occurs in
> > g_mime_encoding_quoted_encode_step.
> >
> > I think the reason is that GMIME_QP_ENCODE_LEN looks like:
> >
> > #define GMIME_QP_ENCODE_LEN(x) ((size_t) ((((x) + 1) * 3) + 1))
> >
> > is wrong because g_mime_encoding_quoted_encode_step inserts an EOL
> > char after every 74th output character which the macro doesn't take
> > into account. The bug doesn't occur if using base64 encoding.
> >
> >
>
> try this macro:
>
> #define GMIME_QP_ENCODE_LEN(x) ((size_t) ((((x) / 24) * 73) + 74))
I couldn't test it on weekend but I've tested it now and it still crashes
in my case. I took another look at the code and this computation
doesn't account the worst case: gmime-encodings.c:972 inserts "=\n"
every 72 chars. I calculated and tested that this works for me:
((size_t) ((((x) / 12) * 37) + 39))
This adds 2 chars ("=\n") for every input char assuming that every input
char may need encoding.
This is my test program and the test file is attached:
static void encoding_test (int fd)
{
const size_t buf_size = 4 * 1024;
char *buf;
ssize_t res;
GMimeEncoding state;
buf = malloc (buf_size);
g_mime_encoding_init_encode (&state, GMIME_CONTENT_ENCODING_QUOTEDPRINTABLE);
//g_mime_encoding_init_encode (&state, GMIME_CONTENT_ENCODING_BASE64);
while ((res = read(fd, buf, buf_size)) > 0) {
char *outbuf = malloc (g_mime_encoding_outlen(&state, res));
size_t outLen;
outLen = g_mime_encoding_step (&state, buf, res, outbuf);
res = write (1, outbuf, outLen);
if (res < 0) {
perror ("write");
return;
}
free (outbuf);
}
if (res < 0) {
perror ("read");
}
char *outbuf = malloc (g_mime_encoding_outlen(&state, res));
size_t outLen = g_mime_encoding_flush (&state, buf, res, outbuf);
res = write (1, outbuf, outLen);
if (res < 0) {
perror ("write");
return;
}
free (outbuf);
}
--
Damian Pietras
http://www.linuxprogrammingblog.com
Attachment:
Testowy1.doc
Description: MS-Word document