[gmime] gmime_multipart_foreach: avoid stack overflow from recursion
- From: Rico Tzschichholz <ricotz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gmime] gmime_multipart_foreach: avoid stack overflow from recursion
- Date: Sat, 21 Dec 2019 16:58:59 +0000 (UTC)
commit 6d7c904e52bdfd723db990a326527fd65e45320a
Author: Eric Wong <e 80x24 org>
Date: Sat Nov 9 07:55:45 2019 -0500
gmime_multipart_foreach: avoid stack overflow from recursion
We can use a GQueue to emulate the behavior of an stack on the
heap. This allows us to parse deeply nested MIME parts since
RLIMIT_STACK is typically only a few megabytes while typical
GNU/Linux systems can use all available virtual memory for the
heap.
gmime/gmime-multipart.c | 52 ++++++++++++++++++++++++++++++++++---------------
1 file changed, 36 insertions(+), 16 deletions(-)
---
diff --git a/gmime/gmime-multipart.c b/gmime/gmime-multipart.c
index ade11d5b..f27dbb51 100644
--- a/gmime/gmime-multipart.c
+++ b/gmime/gmime-multipart.c
@@ -775,22 +775,10 @@ g_mime_multipart_get_boundary (GMimeMultipart *multipart)
return GMIME_MULTIPART_GET_CLASS (multipart)->get_boundary (multipart);
}
-
-static void
-multipart_foreach (GMimeMultipart *multipart, GMimeObjectForeachFunc callback, gpointer user_data)
-{
+typedef struct _GMimeForeachData {
+ GMimeObject *parent;
GMimeObject *part;
- guint i;
-
- for (i = 0; i < multipart->children->len; i++) {
- part = (GMimeObject *) multipart->children->pdata[i];
- callback ((GMimeObject *) multipart, part, user_data);
-
- if (GMIME_IS_MULTIPART (part))
- multipart_foreach ((GMimeMultipart *) part, callback, user_data);
- }
-}
-
+} GMimeForeachData;
/**
* g_mime_multipart_foreach:
@@ -804,10 +792,42 @@ multipart_foreach (GMimeMultipart *multipart, GMimeObjectForeachFunc callback, g
void
g_mime_multipart_foreach (GMimeMultipart *multipart, GMimeObjectForeachFunc callback, gpointer user_data)
{
+ GMimeForeachData *tmp;
+ GQueue *queue;
+ guint i;
g_return_if_fail (GMIME_IS_MULTIPART (multipart));
g_return_if_fail (callback != NULL);
- multipart_foreach (multipart, callback, user_data);
+ tmp = g_malloc (sizeof (GMimeForeachData));
+ queue = g_queue_new ();
+
+ tmp->parent = (GMimeObject *) multipart;
+ tmp->part = (GMimeObject *) multipart;
+
+ g_queue_push_tail (queue, tmp);
+
+ while ((tmp = (GMimeForeachData *) g_queue_pop_head (queue))) {
+ GMimeObject *parent = tmp->parent;
+ GMimeObject *part = tmp->part;
+
+ g_free (tmp);
+ if (part != parent)
+ callback (parent, part, user_data);
+
+ if (GMIME_IS_MULTIPART (part)) {
+ multipart = (GMimeMultipart *) part;
+ i = multipart->children->len;
+ while (i > 0) {
+ tmp = g_malloc (sizeof (GMimeForeachData));
+ tmp->parent = part;
+ tmp->part = (GMimeObject *) multipart->children->pdata[--i];
+
+ g_queue_push_head (queue, tmp);
+ }
+ }
+ }
+
+ g_queue_free (queue);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]