xorl %eax, %eax

CVE-2009-1375: Pidgin Memory Corruption

leave a comment »

This issue was reported by Josef Andrysek and affects pidgin prior to 2.5.6 release. Here is the vulnerability as seen in 2.5.5 release of the popular instant messaging application:

1 /*
2  * @file circbuffer.h Buffer Utility Functions
3  * @ingroup core
4  */
       ...
44 static void grow_circ_buffer(PurpleCircBuffer *buf, gsize len) {
45         int in_offset = 0, out_offset = 0;
46         int start_buflen;
       ...
50         start_buflen = buf->buflen;
       ...
55         if (buf->inptr != NULL) {
56                 in_offset = buf->inptr - buf->buffer;
57                 out_offset = buf->outptr - buf->buffer;
58         }
       ...
69         /* If the fill pointer is wrapped to before the remove
70          * pointer, we need to shift the data */
71         if (in_offset < out_offset) {
72                 int shift_n = MIN(buf->buflen - start_buflen,
73                         in_offset);
74                 memcpy(buf->buffer + start_buflen, buf->buffer,
75                         shift_n);
       ...
90 }

This is located at libpurple/circbuffer.c and it used to handle the PurpleCircBuffer circular buffer structure defined in libpurple/circbuffer.h. The above routine is used to grow a buffer passed to it (it is implied by its name as well). Josef Andrysek noticed that if the buffer passed to this function is already full. Meaning that at lines 56 and 57 the input offset and the output one will contain the same values, the check at line 71 will be bypassed and the following call to memcpy() (line 74) will result in memory corruption. Variable shift_n which represents the bytes to be copied is initialized at lines 72-73. To fix this the following patch was applied:

        /* If the fill pointer is wrapped to before the remove
         * pointer, we need to shift the data */
-       if (in_offset < out_offset) {
+       if (in_offset < out_offset
+                       || (in_offset == out_offset && buf->bufused > 0)) {
                int shift_n = MIN(buf->buflen - start_buflen,

Now it checks for cases of a buffer where the two offsets are equal as well as that the size of the unread bytes in the buffer is greater than zero.

Written by xorl

May 27, 2009 at 10:58

Posted in bugs

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s