Bugzilla – Attachment 192906 Details for
Bug 333292
beagled leaks memory
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Forgot Password
[patch]
bnc-333292.patch
bnc-333292.patch (text/plain), 21.27 KB, created by
Jeff Stedfast
on 2008-02-02 19:16:28 UTC
(
hide
)
Description:
bnc-333292.patch
Filename:
MIME Type:
Creator:
Jeff Stedfast
Created:
2008-02-02 19:16:28 UTC
Size:
21.27 KB
patch
obsolete
>--- gmime-2.2.15/gmime/gmime-parser.c 2008-01-01 09:54:13.000000000 -0500 >+++ gmime/gmime/gmime-parser.c 2008-02-02 13:53:19.000000000 -0500 >@@ -1,6 +1,6 @@ > /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ > /* GMime >- * Copyright (C) 2000-2007 Jeffrey Stedfast >+ * Copyright (C) 2000-2008 Jeffrey Stedfast > * > * This library is free software; you can redistribute it and/or > * modify it under the terms of the GNU Lesser General Public License >@@ -30,6 +30,7 @@ > > #include "gmime-parser.h" > >+#include "gmime-table-private.h" > #include "gmime-stream-mem.h" > #include "gmime-message-part.h" > #include "gmime-multipart.h" >@@ -80,11 +81,10 @@ enum { > GMIME_PARSER_STATE_HEADERS, > GMIME_PARSER_STATE_HEADERS_END, > GMIME_PARSER_STATE_CONTENT, >+ GMIME_PARSER_STATE_COMPLETE, > }; > > struct _GMimeParserPrivate { >- int state; >- > GMimeStream *stream; > > off_t offset; >@@ -115,7 +115,7 @@ struct _GMimeParserPrivate { > off_t headers_start; > off_t header_start; > >- unsigned int unstep:26; >+ int state:26; > unsigned int midline:1; > unsigned int seekable:1; > unsigned int scan_from:1; >@@ -326,7 +326,6 @@ parser_init (GMimeParser *parser, GMimeS > priv->headers_start = -1; > priv->header_start = -1; > >- priv->unstep = 0; > priv->midline = FALSE; > priv->seekable = offset != -1; > >@@ -354,14 +353,6 @@ parser_close (GMimeParser *parser) > parser_pop_boundary (parser); > } > >-static void >-parser_unstep (GMimeParser *parser) >-{ >- struct _GMimeParserPrivate *priv = parser->priv; >- >- priv->unstep++; >-} >- > > /** > * g_mime_parser_new: >@@ -793,49 +784,73 @@ parser_step_from (GMimeParser *parser) > priv->rawptr = priv->rawbuf; \ > } G_STMT_END > >-#define header_parse(parser, priv, hend) G_STMT_START { \ >- struct _header_raw *header; \ >- register char *colon; \ >- size_t hlen; \ >- \ >- header = g_new (struct _header_raw, 1); \ >- header->next = NULL; \ >- \ >- *priv->headerptr = '\0'; \ >- colon = priv->headerbuf; \ >- while (*colon && *colon != ':') \ >- colon++; \ >- \ >- hlen = colon - priv->headerbuf; \ >- \ >- header->name = g_strndup (priv->headerbuf, hlen); \ >- g_strstrip (header->name); \ >- if (*colon != ':') { \ >- w(g_warning ("Invalid header: %s", header->name)); \ >- header->value = header->name; \ >- header->name = g_strdup ("X-Invalid-Header"); \ >- } else { \ >- header->value = g_strdup (colon + 1); \ >- g_strstrip (header->value); \ >- } \ >- header->offset = priv->header_start; \ >- \ >- hend->next = header; \ >- hend = header; \ >- \ >- priv->headerleft += priv->headerptr - priv->headerbuf; \ >- priv->headerptr = priv->headerbuf; \ >- \ >- if (priv->have_regex && \ >- !regexec (&priv->header_regex, header->name, 0, NULL, 0)) \ >- priv->header_cb (parser, header->name, header->value, \ >- header->offset, priv->user_data); \ >-} G_STMT_END >+static void >+header_parse (GMimeParser *parser, struct _header_raw **tail) >+{ >+ struct _GMimeParserPrivate *priv = parser->priv; >+ struct _header_raw *header; >+ register char *inptr, *end; >+ char *start; >+ size_t hlen; >+ >+ header = g_new (struct _header_raw, 1); >+ header->next = NULL; >+ >+ *priv->headerptr = '\0'; >+ inptr = priv->headerbuf; >+ while (*inptr && *inptr != ':' && !is_type (*inptr, IS_SPACE | IS_CTRL)) >+ inptr++; >+ >+ if (*inptr != ':') { >+ /* ignore invalid headers */ >+ w(g_warning ("Invalid header at %lld: '%s'", >+ (long long) priv->header_start, >+ priv->headerbuf)); >+ >+ priv->headerleft += priv->headerptr - priv->headerbuf; >+ priv->headerptr = priv->headerbuf; >+ >+ return; >+ } >+ >+ hlen = inptr - priv->headerbuf; >+ header->name = g_strndup (priv->headerbuf, hlen); >+ >+ /* skip over leading lwsp */ >+ inptr++; >+ while (is_lwsp (*inptr)) >+ inptr++; >+ >+ /* cut trailing lwsp */ >+ start = inptr++; >+ end = inptr; >+ >+ while (*inptr) { >+ if (!is_lwsp (*inptr++)) >+ end = inptr; >+ } >+ >+ header->value = g_strndup (start, end - start); >+ >+ header->offset = priv->header_start; >+ >+ (*tail)->next = header; >+ *tail = header; >+ >+ priv->headerleft += priv->headerptr - priv->headerbuf; >+ priv->headerptr = priv->headerbuf; >+ >+ if (priv->have_regex && >+ !regexec (&priv->header_regex, header->name, 0, NULL, 0)) >+ priv->header_cb (parser, header->name, header->value, >+ header->offset, priv->user_data); >+} > > static int > parser_step_headers (GMimeParser *parser) > { > struct _GMimeParserPrivate *priv = parser->priv; >+ gboolean valid = TRUE, fieldname = TRUE; > struct _header_raw *hend; > register char *inptr; > char *start, *inend; >@@ -843,6 +858,8 @@ parser_step_headers (GMimeParser *parser > size_t len; > > priv->midline = FALSE; >+ raw_header_reset (priv); >+ header_raw_clear (&priv->headers); > hend = (struct _header_raw *) &priv->headers; > priv->headers_start = parser_offset (priv, NULL); > priv->header_start = parser_offset (priv, NULL); >@@ -864,6 +881,48 @@ parser_step_headers (GMimeParser *parser > > while (inptr < inend) { > start = inptr; >+ >+ if (fieldname && *inptr != '\n') { >+ /* scan and validate the field name */ >+ if (*inptr != ':') { >+ *inend = ':'; >+ while (*inptr != ':') { >+ if (is_type (*inptr, IS_SPACE | IS_CTRL)) { >+ valid = FALSE; >+ break; >+ } >+ >+ inptr++; >+ } >+ >+ if (inptr == inend) { >+ /* don't have the full field name */ >+ left = inend - start; >+ priv->inptr = start; >+ goto refill; >+ } >+ >+ *inend = '\n'; >+ } else if (*inptr == ':') { >+ valid = FALSE; >+ } >+ >+ if (!valid) { >+ if (priv->scan_from && (inptr - start) == 4 >+ && !strncmp (start, "From ", 5)) >+ goto next_message; >+ >+ if (priv->headers != NULL || *inptr == ':') { >+ /* probably the start of the content, >+ * a broken mailer didn't terminate the >+ * headers with an empty line. *sigh* */ >+ goto content_start; >+ } >+ } >+ } >+ >+ fieldname = FALSE; >+ > /* Note: see optimization comment [1] */ > while (*inptr != '\n') > inptr++; >@@ -897,9 +956,11 @@ parser_step_headers (GMimeParser *parser > if (*inptr == ' ' || *inptr == '\t') { > priv->midline = TRUE; > } else { >- priv->midline = FALSE; >- header_parse (parser, priv, hend); >+ header_parse (parser, &hend); > priv->header_start = parser_offset (priv, inptr); >+ priv->midline = FALSE; >+ fieldname = TRUE; >+ valid = TRUE; > } > } > >@@ -917,15 +978,27 @@ parser_step_headers (GMimeParser *parser > headers_end: > > if (priv->headerptr > priv->headerbuf) >- header_parse (parser, priv, hend); >+ header_parse (parser, &hend); > >+ priv->state = GMIME_PARSER_STATE_HEADERS_END; > *priv->rawptr = '\0'; >+ priv->inptr = inptr; > >- priv->state = GMIME_PARSER_STATE_HEADERS_END; >+ return 0; > >- g_assert (inptr <= priv->inend); >+ next_message: > >- priv->inptr = inptr; >+ priv->state = GMIME_PARSER_STATE_COMPLETE; >+ *priv->rawptr = '\0'; >+ priv->inptr = start; >+ >+ return 0; >+ >+ content_start: >+ >+ priv->state = GMIME_PARSER_STATE_CONTENT; >+ *priv->rawptr = '\0'; >+ priv->inptr = start; > > return 0; > } >@@ -943,54 +1016,14 @@ parser_content_type (GMimeParser *parser > } > > static int >-parser_step (GMimeParser *parser) >-{ >- struct _GMimeParserPrivate *priv = parser->priv; >- >- if (!priv->unstep) { >- step: >- switch (priv->state) { >- case GMIME_PARSER_STATE_INIT: >- if (priv->scan_from) >- priv->state = GMIME_PARSER_STATE_FROM; >- else >- priv->state = GMIME_PARSER_STATE_HEADERS; >- goto step; >- break; >- case GMIME_PARSER_STATE_FROM: >- parser_step_from (parser); >- break; >- case GMIME_PARSER_STATE_HEADERS: >- parser_step_headers (parser); >- break; >- case GMIME_PARSER_STATE_ERROR: >- break; >- default: >- g_assert_not_reached (); >- break; >- } >- } else { >- priv->unstep--; >- } >- >- return priv->state; >-} >- >-static void > parser_skip_line (GMimeParser *parser) > { > struct _GMimeParserPrivate *priv = parser->priv; > register char *inptr; > char *inend; >- >- inptr = priv->inptr; >+ int rv = 0; > > do { >- if (parser_fill (parser) <= 0) { >- inptr = priv->inptr; >- break; >- } >- > inptr = priv->inptr; > inend = priv->inend; > *inend = '\n'; >@@ -1002,15 +1035,63 @@ parser_skip_line (GMimeParser *parser) > break; > > priv->inptr = inptr; >+ >+ if (parser_fill (parser) <= 0) { >+ inptr = priv->inptr; >+ rv = -1; >+ break; >+ } > } while (1); > > priv->midline = FALSE; > > priv->inptr = MIN (inptr + 1, priv->inend); >+ >+ return rv; >+} >+ >+static int >+parser_step (GMimeParser *parser) >+{ >+ struct _GMimeParserPrivate *priv = parser->priv; >+ >+ switch (priv->state) { >+ case GMIME_PARSER_STATE_ERROR: >+ break; >+ case GMIME_PARSER_STATE_INIT: >+ if (priv->scan_from) >+ priv->state = GMIME_PARSER_STATE_FROM; >+ else >+ priv->state = GMIME_PARSER_STATE_HEADERS; >+ break; >+ case GMIME_PARSER_STATE_FROM: >+ parser_step_from (parser); >+ break; >+ case GMIME_PARSER_STATE_HEADERS: >+ parser_step_headers (parser); >+ break; >+ case GMIME_PARSER_STATE_HEADERS_END: >+ if (parser_skip_line (parser) == -1) >+ priv->state = GMIME_PARSER_STATE_ERROR; >+ else >+ priv->state = GMIME_PARSER_STATE_CONTENT; >+ break; >+ case GMIME_PARSER_STATE_CONTENT: >+ break; >+ case GMIME_PARSER_STATE_COMPLETE: >+ break; >+ default: >+ g_assert_not_reached (); >+ break; >+ } >+ >+ return priv->state; > } > >+ > enum { >- FOUND_EOS = 1, >+ FOUND_NOTHING, >+ FOUND_EOS, > FOUND_BOUNDARY, > FOUND_END_BOUNDARY > }; >@@ -1076,7 +1157,7 @@ check_boundary (struct _GMimeParserPriva > **/ > > static int >-parser_scan_content (GMimeParser *parser, GByteArray *content, guint *crlf) >+parser_scan_content (GMimeParser *parser, GByteArray *content, int *crlf) > { > struct _GMimeParserPrivate *priv = parser->priv; > register char *inptr; >@@ -1137,7 +1218,7 @@ parser_scan_content (GMimeParser *parser > goto refill; > } > >- /* check for a boundary not ending in a \n */ >+ /* check for a boundary not ending in a \n (EOF) */ > if ((found = check_boundary (priv, start, len))) > goto boundary; > } >@@ -1174,7 +1255,9 @@ parser_scan_mime_part_content (GMimePars > GMimeDataWrapper *wrapper; > GMimeStream *stream; > off_t start, end; >- guint crlf; >+ int crlf; >+ >+ g_assert (priv->state >= GMIME_PARSER_STATE_HEADERS_END); > > if (priv->persist_stream && priv->seekable) > start = parser_offset (priv, NULL); >@@ -1194,11 +1277,10 @@ parser_scan_mime_part_content (GMimePars > > encoding = g_mime_part_get_encoding (mime_part); > >- if (priv->persist_stream && priv->seekable) { >+ if (priv->persist_stream && priv->seekable) > stream = g_mime_stream_substream (priv->stream, start, end); >- } else { >+ else > stream = g_mime_stream_mem_new_with_byte_array (content); >- } > > wrapper = g_mime_data_wrapper_new_with_stream (stream, encoding); > g_mime_part_set_content_object (mime_part, wrapper); >@@ -1215,10 +1297,16 @@ parser_scan_message_part (GMimeParser *p > GMimeMessage *message; > GMimeObject *object; > >+ g_assert (priv->state == GMIME_PARSER_STATE_CONTENT); >+ > /* get the headers */ >- parser->priv->state = GMIME_PARSER_STATE_HEADERS; >- while (parser_step (parser) != GMIME_PARSER_STATE_HEADERS_END) >- ; >+ priv->state = GMIME_PARSER_STATE_HEADERS; >+ if (parser_step (parser) == -1) { >+ /* Note: currently cannot happen because >+ * parser_step_headers() never returns error */ >+ *found = FOUND_EOS; >+ return; >+ } > > message = g_mime_message_new (FALSE); > header = priv->headers; >@@ -1230,12 +1318,10 @@ parser_scan_message_part (GMimeParser *p > if (!(content_type = parser_content_type (parser))) > content_type = g_mime_content_type_new ("text", "plain"); > >- parser_unstep (parser); >- if (g_mime_content_type_is_type (content_type, "multipart", "*")) { >+ if (g_mime_content_type_is_type (content_type, "multipart", "*")) > object = parser_construct_multipart (parser, content_type, found); >- } else { >+ else > object = parser_construct_leaf_part (parser, content_type, found); >- } > > message->mime_part = object; > >@@ -1250,11 +1336,10 @@ parser_construct_leaf_part (GMimeParser > struct _header_raw *header; > GMimeObject *object; > >- /* get the headers */ >- while (parser_step (parser) != GMIME_PARSER_STATE_HEADERS_END) >- ; >+ g_assert (priv->state >= GMIME_PARSER_STATE_HEADERS_END); > > object = g_mime_object_new_type (content_type->type, content_type->subtype); >+ > header = priv->headers; > while (header) { > g_mime_object_add_header (object, header->name, header->value); >@@ -1270,14 +1355,18 @@ parser_construct_leaf_part (GMimeParser > g_mime_header_set_raw (object->headers, priv->rawbuf); > raw_header_reset (priv); > >- /* skip empty line after headers */ >- parser_skip_line (parser); >+ if (priv->state == GMIME_PARSER_STATE_HEADERS_END) { >+ /* skip empty line after headers */ >+ if (parser_step (parser) == -1) { >+ *found = FOUND_EOS; >+ return object; >+ } >+ } > >- if (GMIME_IS_MESSAGE_PART (object)) { >+ if (GMIME_IS_MESSAGE_PART (object)) > parser_scan_message_part (parser, (GMimeMessagePart *) object, found); >- } else { >+ else > parser_scan_mime_part_content (parser, (GMimePart *) object, found); >- } > > return object; > } >@@ -1311,9 +1400,8 @@ static int > parser_scan_multipart_face (GMimeParser *parser, GMimeMultipart *multipart, gboolean preface) > { > GByteArray *buffer; >- guint crlf; >+ int found, crlf; > char *face; >- int found; > > buffer = g_byte_array_new (); > found = parser_scan_content (parser, buffer, &crlf); >@@ -1339,45 +1427,58 @@ parser_scan_multipart_face (GMimeParser > #define parser_scan_multipart_preface(parser, multipart) parser_scan_multipart_face (parser, multipart, TRUE) > #define parser_scan_multipart_postface(parser, multipart) parser_scan_multipart_face (parser, multipart, FALSE) > >+static gboolean >+found_immediate_boundary (struct _GMimeParserPrivate *priv, gboolean end) >+{ >+ struct _boundary_stack *s = priv->bounds; >+ size_t len = end ? s->boundarylenfinal : s->boundarylen; >+ >+ return !strncmp (priv->inptr, s->boundary, len) >+ && (priv->inptr[len] == '\n' || priv->inptr[len] == '\r'); >+} >+ > static int > parser_scan_multipart_subparts (GMimeParser *parser, GMimeMultipart *multipart) > { >+ struct _GMimeParserPrivate *priv = parser->priv; > GMimeContentType *content_type; > GMimeObject *subpart; > int found; > > do { > /* skip over the boundary marker */ >- parser_skip_line (parser); >+ if (parser_skip_line (parser) == -1) { >+ found = FOUND_EOS; >+ break; >+ } > > /* get the headers */ >- parser_step_headers (parser); >+ priv->state = GMIME_PARSER_STATE_HEADERS; >+ if (parser_step (parser) == -1) { >+ found = FOUND_EOS; >+ break; >+ } >+ >+ if (priv->state == GMIME_PARSER_STATE_COMPLETE && priv->headers == NULL) { >+ found = FOUND_END_BOUNDARY; >+ break; >+ } > > if (!(content_type = parser_content_type (parser))) > content_type = g_mime_content_type_new ("text", "plain"); > >- parser_unstep (parser); >- if (g_mime_content_type_is_type (content_type, "multipart", "*")) { >+ if (g_mime_content_type_is_type (content_type, "multipart", "*")) > subpart = parser_construct_multipart (parser, content_type, &found); >- } else { >+ else > subpart = parser_construct_leaf_part (parser, content_type, &found); >- } > > g_mime_multipart_add_part (multipart, subpart); > g_object_unref (subpart); >- } while (found == FOUND_BOUNDARY); >+ } while (found == FOUND_BOUNDARY && found_immediate_boundary (priv, FALSE)); > > return found; > } > >-static gboolean >-found_immediate_boundary (struct _GMimeParserPrivate *priv) >-{ >- struct _boundary_stack *s = priv->bounds; >- >- return !strncmp (s->boundary, priv->inptr, s->boundarylenfinal); >-} >- > static GMimeObject * > parser_construct_multipart (GMimeParser *parser, GMimeContentType *content_type, int *found) > { >@@ -1387,11 +1488,10 @@ parser_construct_multipart (GMimeParser > const char *boundary; > GMimeObject *object; > >- /* get the headers */ >- while (parser_step (parser) != GMIME_PARSER_STATE_HEADERS_END) >- ; >+ g_assert (priv->state >= GMIME_PARSER_STATE_HEADERS_END); > > object = g_mime_object_new_type (content_type->type, content_type->subtype); >+ > header = priv->headers; > while (header) { > g_mime_object_add_header (object, header->name, header->value); >@@ -1409,8 +1509,13 @@ parser_construct_multipart (GMimeParser > > multipart = (GMimeMultipart *) object; > >- /* skip empty line after headers */ >- parser_skip_line (parser); >+ if (priv->state == GMIME_PARSER_STATE_HEADERS_END) { >+ /* skip empty line after headers */ >+ if (parser_step (parser) == -1) { >+ *found = FOUND_EOS; >+ return object; >+ } >+ } > > boundary = g_mime_content_type_get_parameter (content_type, "boundary"); > if (boundary) { >@@ -1421,7 +1526,7 @@ parser_construct_multipart (GMimeParser > if (*found == FOUND_BOUNDARY) > *found = parser_scan_multipart_subparts (parser, multipart); > >- if (*found == FOUND_END_BOUNDARY && found_immediate_boundary (priv)) { >+ if (*found == FOUND_END_BOUNDARY && found_immediate_boundary (priv, TRUE)) { > /* eat end boundary */ > parser_skip_line (parser); > parser_pop_boundary (parser); >@@ -1441,23 +1546,24 @@ parser_construct_multipart (GMimeParser > static GMimeObject * > parser_construct_part (GMimeParser *parser) > { >+ struct _GMimeParserPrivate *priv = parser->priv; > GMimeContentType *content_type; > GMimeObject *object; > int found; > > /* get the headers */ >- while (parser_step (parser) != GMIME_PARSER_STATE_HEADERS_END) >- ; >+ while (priv->state < GMIME_PARSER_STATE_HEADERS_END) { >+ if (parser_step (parser) == -1) >+ return NULL; >+ } > > if (!(content_type = parser_content_type (parser))) > content_type = g_mime_content_type_new ("text", "plain"); > >- parser_unstep (parser); >- if (g_mime_content_type_is_type (content_type, "multipart", "*")) { >+ if (g_mime_content_type_is_type (content_type, "multipart", "*")) > object = parser_construct_multipart (parser, content_type, &found); >- } else { >+ else > object = parser_construct_leaf_part (parser, content_type, &found); >- } > > return object; > } >@@ -1484,25 +1590,34 @@ static GMimeMessage * > parser_construct_message (GMimeParser *parser) > { > struct _GMimeParserPrivate *priv = parser->priv; >+ unsigned int content_length = ULONG_MAX; > GMimeContentType *content_type; > struct _header_raw *header; >- int content_length = -1; > GMimeMessage *message; > GMimeObject *object; >- int state, found; >+ char *endptr; >+ int found; > >- /* get the headers (and, optionally, the from-line) */ >- while ((state = parser_step (parser)) != GMIME_PARSER_STATE_ERROR && state != GMIME_PARSER_STATE_HEADERS_END) >- ; >+ /* scan the from-line if we are parsing an mbox */ >+ while (priv->state != GMIME_PARSER_STATE_HEADERS) { >+ if (parser_step (parser) == -1) >+ return NULL; >+ } > >- if (state == GMIME_PARSER_STATE_ERROR) >- return NULL; >+ /* parse the headers */ >+ while (priv->state < GMIME_PARSER_STATE_HEADERS_END) { >+ if (parser_step (parser) == -1) >+ return NULL; >+ } > > message = g_mime_message_new (FALSE); > header = priv->headers; > while (header) { >- if (priv->respect_content_length && !g_ascii_strcasecmp (header->name, "Content-Length")) >- content_length = strtoul (header->value, NULL, 10); >+ if (priv->respect_content_length && !g_ascii_strcasecmp (header->name, "Content-Length")) { >+ content_length = strtoul (header->value, &endptr, 10); >+ if (endptr == header->value) >+ content_length = ULONG_MAX; >+ } > > g_mime_object_add_header ((GMimeObject *) message, header->name, header->value); > header = header->next; >@@ -1510,19 +1625,17 @@ parser_construct_message (GMimeParser *p > > if (priv->scan_from) { > parser_push_boundary (parser, "From "); >- if (priv->respect_content_length && content_length != -1) >+ if (priv->respect_content_length && content_length < ULONG_MAX) > priv->bounds->content_end = parser_offset (priv, NULL) + content_length; > } > > if (!(content_type = parser_content_type (parser))) > content_type = g_mime_content_type_new ("text", "plain"); > >- parser_unstep (parser); >- if (content_type && g_mime_content_type_is_type (content_type, "multipart", "*")) { >+ if (content_type && g_mime_content_type_is_type (content_type, "multipart", "*")) > object = parser_construct_multipart (parser, content_type, &found); >- } else { >+ else > object = parser_construct_leaf_part (parser, content_type, &found); >- } > > message->mime_part = object; >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
Actions:
View
|
Diff
Attachments on
bug 333292
:
192025
|
192037
| 192906