Re: [gmime-devel] Wrong results of g_mime_encoding_outlen



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



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]