talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

commit b7e94940ec51c96be59bce99d3eaedf53a889bfb
parent fa9de149482e3df257a5271815fad7f5453f17b7
Author: wwp <subscript@free.fr>
Date:   Sun,  6 Sep 2020 11:41:34 +0200

Fix bug 4313 "Recursion stack overflow with rebuilding folder tree" by
limiting the IMAP rebuild-folder-tree recursion depth to 64 (hidden pref).

Diffstat:
Msrc/imap.c | 33+++++++++++++++++++++++++++++++--
Msrc/prefs_common.c | 2++
Msrc/prefs_common.h | 1+
3 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/src/imap.c b/src/imap.c @@ -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 @@ -2752,6 +2757,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; FolderItem *new_item; @@ -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); diff --git a/src/prefs_common.c b/src/prefs_common.c @@ -1159,6 +1159,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", diff --git a/src/prefs_common.h b/src/prefs_common.h @@ -535,6 +535,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;