Re: [gmime-devel] Double free crash in g_mime_header_list_register_writer()



Hi Jeff

Thanks a lot, I'll probably change to a source install.

If anyone has trouble with this, this hack works. Bring the struct
defines in scope:

typedef struct _ListNode {
struct _ListNode *next;
struct _ListNode *prev;
} ListNode;

typedef struct {
ListNode *head;
ListNode *tail;
ListNode *tailpred;
} List;

typedef struct _GMimeEvent GMimeEvent;

struct _GMimeHeaderList {
GMimeStream *stream;
GHashTable *writers;
GMimeEvent *changed;
GHashTable *hash;
guint32 version;
List list;
};

void g_mime_header_list_register_writer_fixed (GMimeHeaderList
*headers, const char *name, GMimeHeaderWriter writer)
{
gpointer okey, oval;
g_return_if_fail (headers != NULL);
g_return_if_fail (name != NULL);
g_hash_table_remove(headers->writers, name);
if (writer)
g_hash_table_insert (headers->writers, g_strdup (name), writer);
}


On Fri, Jul 18, 2014 at 2:51 PM, Jeffrey Stedfast <fejj gnome org> wrote:
Hi Johan,

Looks like there is indeed a double-free. I just read over the documentation
and g_hash_table_remove() free's the key for us, so there's no need to free
it (again).

The fix is to replace the whole g_hash_table_lookup if-block with:

g_hash_table_remove (headers->writers, name);

I've committed a fix to git master, but git master is 2.6.21, not 2.4.21

Hope that helps,

Jeff

On 7/18/2014 7:09 AM, Johan van den Berg wrote:

Hi

I am using gmime 2.4.21 (installed with yum on RHEL6) and glib2
2.26.1, and I am trying to disable header folding.

The crash occurs when calling g_mime_header_list_register_writer().

Is there something I am missing?


Regards
Johan



*** glibc detected *** ./gmimetest: double free or corruption
(fasttop): 0x0000000002552910 ***
======= Backtrace: =========
/lib64/libc.so.6[0x3209475916]

/usr/lib64/libgmime-2.4.so.2(g_mime_header_list_register_writer+0x62)[0x32fee1c642]
./gmimetest[0x401c13]
./gmimetest[0x4021c7]
/lib64/libc.so.6(__libc_start_main+0xfd)[0x320941ecdd]
./gmimetest[0x401619]

This happens when g_free(okey) is called after
g_hash_lookup_extended() is called. As far as I can tell from my
debugger, okey points to an empty string, however I don't know glib
hash tables very well so this might not be relevant.

Snippet from cgdb in /usr/src/debug/gmime-2.4.21/gmime/gmime-header.c:

  924| void
  925| g_mime_header_list_register_writer (GMimeHeaderList *headers,
const char *name, GMimeHeaderWriter writer)
  926| {
  927|         gpointer okey, oval;
  928|
  929|         g_return_if_fail (headers != NULL);
  930|         g_return_if_fail (name != NULL);
  931|
  932|         if (g_hash_table_lookup (headers->writers, name)) {
  933|                 g_hash_table_lookup_extended (headers->writers,
name, &okey, &oval);
  934|                 g_hash_table_remove (headers->writers, name);
  935+>                g_free (okey);
  936|         }
  937|
  938|         if (writer)
  939|                 g_hash_table_insert (headers->writers, g_strdup
(name), writer);
  940| }


My offending code snippet:

--------------------------

#include <glib.h>
#include <gmime/gmime.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

void build_multipart(void);
ssize_t nonfolding_mime_header_writer (GMimeStream *stream, const char
* name, const char * value);
char * nonfolding_mime_header_printf(const char * format, ...);

int main (int argc, char **argv)
{
     g_mime_init (0);

     build_multipart();

     return 0;
}

void build_multipart(void)
{
     GMimeMultipart * multipart;
     GMimeHeaderList * headers;

     multipart = g_mime_multipart_new_with_subtype("related");
     headers = g_mime_object_get_header_list((GMimeObject *) multipart);
     g_mime_object_set_content_type_parameter((GMimeObject *)
multipart, "type", "text/xml");
     g_mime_object_set_content_type_parameter((GMimeObject *)
multipart, "start", "<xyz>");
     g_mime_header_list_register_writer(headers, "Content-Type",
nonfolding_mime_header_writer);
}

ssize_t nonfolding_mime_header_writer (GMimeStream *stream, const char
* name, const char * value)
{
ssize_t     nwritten;
char *      val;
val = nonfolding_mime_header_printf ("%s: %s\n", name, value);
nwritten = g_mime_stream_write_string (stream, val);
g_free (val);
return nwritten;
}

char * nonfolding_mime_header_printf(const char * format, ...)
{
char *  buf;
va_list ap;
va_start (ap, format);
buf = g_strdup_vprintf (format, ap);
va_end (ap);
return buf;
}

--------------------------
_______________________________________________
gmime-devel-list mailing list
gmime-devel-list gnome org
https://mail.gnome.org/mailman/listinfo/gmime-devel-list





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