Fix bug 4313 "Recursion stack overflow with rebuilding folder tree" by
authorwwp <subscript@free.fr>
Sun, 6 Sep 2020 09:41:34 +0000 (11:41 +0200)
committerwwp <subscript@free.fr>
Sun, 6 Sep 2020 09:41:34 +0000 (11:41 +0200)
limiting the IMAP rebuild-folder-tree recursion depth to 64 (hidden pref).

src/imap.c
src/prefs_common.c
src/prefs_common.h

index 3ab83c50f109a2ec6e0f87dc46338700080e4fc0..43388a5f76f8cb2acd42663a4a985bf0e06cfed8 100644 (file)
@@ -123,6 +123,8 @@ struct _IMAPSession
        gboolean cancelled;
        gboolean sens_update_block;
        gboolean do_destroy;
+
+    gint scan_tree_recurs_depth;
 };
 
 struct _IMAPNameSpace
@@ -278,6 +280,9 @@ static gint imap_auth                       (IMAPSession    *session,
 static gint imap_scan_tree_recursive   (IMAPSession    *session,
                                         FolderItem     *item,
                                         gboolean        subs_only);
+static gint imap_scan_tree_recursive_dive      (IMAPSession    *session,
+                                        FolderItem     *item,
+                                        gboolean        subs_only);
 
 static void imap_create_missing_folders        (Folder         *folder);
 static FolderItem *imap_create_special_folder
@@ -2751,6 +2756,14 @@ static gint imap_scan_tree(Folder *folder)
 }
 
 static gint imap_scan_tree_recursive(IMAPSession *session, FolderItem *item, gboolean subs_only)
+{
+    /* reset recursion depth counter */
+    session->scan_tree_recurs_depth = 0;
+
+    return imap_scan_tree_recursive_dive(session, item, subs_only);
+}
+
+static gint imap_scan_tree_recursive_dive(IMAPSession *session, FolderItem *item, gboolean subs_only)
 {
        Folder *folder;
        IMAPFolder *imapfolder;
@@ -2768,6 +2781,15 @@ static gint imap_scan_tree_recursive(IMAPSession *session, FolderItem *item, gbo
        g_return_val_if_fail(item->folder != NULL, -1);
        g_return_val_if_fail(item->no_sub == FALSE, -1);
 
+    /* recursion depth limiter */
+    if(session->scan_tree_recurs_depth >= prefs_common.imap_scan_tree_recurs_limit) {
+        g_warning("IMAP scan tree recursion limit reached (%d, folder '%s')",
+                prefs_common.imap_scan_tree_recurs_limit, item->folder->name);
+        return -1;
+    }
+    /* entering recursion func: increase depth counter */
+    session->scan_tree_recurs_depth++;
+
        folder = item->folder;
        imapfolder = IMAP_FOLDER(folder);
 
@@ -2895,8 +2917,15 @@ static gint imap_scan_tree_recursive(IMAPSession *session, FolderItem *item, gbo
                        g_free(base);
                }
 
-               if (new_item->no_sub == FALSE)
-                       imap_scan_tree_recursive(session, new_item, subs_only);
+               if (new_item->no_sub == FALSE) {
+                       imap_scan_tree_recursive_dive(session, new_item, subs_only);
+
+            /* entering recursion func: increase depth counter */
+            session->scan_tree_recurs_depth--;
+            if (session->scan_tree_recurs_depth < 0)
+                g_error("IMAP scan tree recursion underflow (%d)",
+                        session->scan_tree_recurs_depth);
+        }
        }
 
        g_slist_free(item_list);
index de52af0c2ab15658253d86cae76ace194bce9c7d..2fe16fd06935fee63e6aae0293f776587c395a12 100644 (file)
@@ -1163,6 +1163,8 @@ static PrefParam param[] = {
         NULL, NULL, NULL},
 
        /* Hidden */
+       {"imap_scan_tree_recurs_limit", "64", &prefs_common.imap_scan_tree_recurs_limit, P_INT,
+        NULL, NULL, NULL},
        {"warn_dnd", "1", &prefs_common.warn_dnd, P_INT,
         NULL, NULL, NULL},
        {"utf8_instead_of_locale_for_broken_mail", "0", 
index d4f746a72d777477f0c175b3715c8e982ab633b8..544e9ddbc4e208dbed8f237958f645dacb19a132 100644 (file)
@@ -537,6 +537,7 @@ struct _PrefsCommon
        gint news_subscribe_width;
        gint news_subscribe_height;
 
+    gint imap_scan_tree_recurs_limit;
        gint warn_dnd;
        gint broken_are_utf8;
        gint skip_ssl_cert_check;