commit 769e25ef391ab03be684aea672bfc6ea45359556
parent 0d14bbccaacd912cd397ddc3d3c9105aa8d2e1ba
Author: Colin Leroy <colin@colino.net>
Date: Sat, 31 May 2008 10:02:22 +0000
2008-05-31 [colin] 3.4.0cvs75
* src/imap.c
Fix more possible double-frees. Also, fix the root cause
of these double-frees by just noting the Session is to
be destroyed instead of destroying it in flight
Diffstat:
4 files changed, 110 insertions(+), 59 deletions(-)
diff --git a/ChangeLog b/ChangeLog
@@ -1,3 +1,10 @@
+2008-05-31 [colin] 3.4.0cvs75
+
+ * src/imap.c
+ Fix more possible double-frees. Also, fix the root cause
+ of these double-frees by just noting the Session is to
+ be destroyed instead of destroying it in flight
+
2008-05-29 [paul] 3.4.0cvs74
* manual/keyboard.xml
diff --git a/PATCHSETS b/PATCHSETS
@@ -3370,3 +3370,4 @@
( cvs diff -u -r 1.20.2.63 -r 1.20.2.64 src/common/utils.h; ) > 3.4.0cvs72.patchset
( cvs diff -u -r 1.60.2.53 -r 1.60.2.54 src/procmsg.h; ) > 3.4.0cvs73.patchset
( cvs diff -u -r 1.1.2.10 -r 1.1.2.11 manual/keyboard.xml; ) > 3.4.0cvs74.patchset
+( cvs diff -u -r 1.179.2.223 -r 1.179.2.224 src/imap.c; ) > 3.4.0cvs75.patchset
diff --git a/configure.ac b/configure.ac
@@ -11,7 +11,7 @@ MINOR_VERSION=4
MICRO_VERSION=0
INTERFACE_AGE=0
BINARY_AGE=0
-EXTRA_VERSION=74
+EXTRA_VERSION=75
EXTRA_RELEASE=
EXTRA_GTK2_VERSION=
diff --git a/src/imap.c b/src/imap.c
@@ -311,10 +311,12 @@ static void imap_commit_tags (FolderItem *item,
static gchar imap_get_path_separator (IMAPSession *session,
IMAPFolder *folder,
- const gchar *path);
+ const gchar *path,
+ gint *ok);
static gchar *imap_get_real_path (IMAPSession *session,
IMAPFolder *folder,
- const gchar *path);
+ const gchar *path,
+ gint *ok);
#ifdef HAVE_LIBETPAN
static void imap_synchronise (FolderItem *item, gint days);
#endif
@@ -533,11 +535,9 @@ static void imap_disc_session_destroy(IMAPSession *session)
return;
if (!session)
return;
- rfolder->session = NULL;
log_warning(LOG_PROTOCOL, _("IMAP4 connection broken\n"));
SESSION(session)->state = SESSION_DISCONNECTED;
SESSION(session)->sock = NULL;
- session_destroy(SESSION(session));
}
static gboolean is_fatal(int libetpan_errcode)
@@ -782,8 +782,7 @@ static int imap_get_capabilities(IMAPSession *session)
capabilities = imap_threaded_capability(session->folder, &result);
if (result != MAILIMAP_NO_ERROR) {
- imap_handle_error(SESSION(session), result);
- return MAILIMAP_ERROR_CAPABILITY;
+ return result;
}
if (capabilities == NULL) {
@@ -822,10 +821,12 @@ static gint imap_auth(IMAPSession *session, const gchar *user, const gchar *pass
static time_t last_login_err = 0;
gchar *ext_info = "";
int r;
+ gchar *server = NULL;
if ((r = imap_get_capabilities(session)) != MAILIMAP_NO_ERROR) {
imap_handle_error(SESSION(session), r);
return r;
}
+ server = g_strdup(SESSION(session)->server);
switch(type) {
case IMAP_AUTH_ANON:
ok = imap_cmd_login(session, user, pass, "ANONYMOUS");
@@ -856,14 +857,11 @@ static gint imap_auth(IMAPSession *session, const gchar *user, const gchar *pass
imap_has_capability(session, "GSSAPI"));
if (imap_has_capability(session, "CRAM-MD5"))
ok = imap_cmd_login(session, user, pass, "CRAM-MD5");
- if ((ok == MAILIMAP_ERROR_BAD_STATE ||
- ok == MAILIMAP_ERROR_LOGIN) && imap_has_capability(session, "DIGEST-MD5"))
+ if (ok == MAILIMAP_ERROR_LOGIN && imap_has_capability(session, "DIGEST-MD5"))
ok = imap_cmd_login(session, user, pass, "DIGEST-MD5");
- if ((ok == MAILIMAP_ERROR_BAD_STATE ||
- ok == MAILIMAP_ERROR_LOGIN) && imap_has_capability(session, "GSSAPI"))
+ if (ok == MAILIMAP_ERROR_LOGIN && imap_has_capability(session, "GSSAPI"))
ok = imap_cmd_login(session, user, pass, "GSSAPI");
- if (ok == MAILIMAP_ERROR_BAD_STATE||
- ok == MAILIMAP_ERROR_LOGIN) /* we always try LOGIN before giving up */
+ if (ok == MAILIMAP_ERROR_LOGIN) /* we always try LOGIN before giving up */
ok = imap_cmd_login(session, user, pass, "LOGIN");
}
@@ -886,15 +884,16 @@ static gint imap_auth(IMAPSession *session, const gchar *user, const gchar *pass
if (!prefs_common.no_recv_err_panel) {
alertpanel_error_log(_("Connection to %s failed: "
"login refused.%s"),
- SESSION(session)->server, ext_info);
+ server, ext_info);
} else {
log_error(LOG_PROTOCOL, _("Connection to %s failed: "
"login refused.%s\n"),
- SESSION(session)->server, ext_info);
+ server, ext_info);
}
}
last_login_err = time(NULL);
}
+ g_free(server);
return ok;
}
@@ -951,12 +950,17 @@ static IMAPSession *imap_session_get(Folder *folder)
}
/* Make sure we have a session */
- if (rfolder->session != NULL) {
+ if (rfolder->session != NULL && rfolder->session->state != SESSION_DISCONNECTED) {
session = IMAP_SESSION(rfolder->session);
+ } else if (rfolder->session != NULL && rfolder->session->state == SESSION_DISCONNECTED) {
+ session_destroy(SESSION(rfolder->session));
+ rfolder->session = NULL;
+ goto new_conn;
} else if (rfolder->connecting) {
debug_print("already connecting\n");
return NULL;
} else {
+new_conn:
imap_reset_uid_lists(folder);
if (time(NULL) - rfolder->last_failure <= 2)
return NULL;
@@ -1181,7 +1185,7 @@ try_again:
goto try_again;
} else {
if (prefs_common.no_recv_err_panel) {
- log_error(LOG_PROTOCOL, _("Couldn't login to IMAP server %s."), account->recv_server);
+ log_error(LOG_PROTOCOL, _("Couldn't login to IMAP server %s.\n"), account->recv_server);
mainwindow_show_error();
} else
alertpanel_error_log(_("Couldn't login to IMAP server %s."), account->recv_server);
@@ -1282,7 +1286,6 @@ static void imap_commit_tags(FolderItem *item, MsgInfo *msginfo, GSList *tags_se
NULL, NULL, NULL, NULL, &can_create_tags, FALSE);
if (ok != MAILIMAP_NO_ERROR) {
- imap_handle_error(SESSION(session), ok);
return;
}
@@ -1576,8 +1579,9 @@ static gint imap_add_msgs(Folder *folder, FolderItem *dest, GSList *file_list,
if (!session) {
return -1;
}
- destdir = imap_get_real_path(session, IMAP_FOLDER(folder), dest->path);
-
+ destdir = imap_get_real_path(session, IMAP_FOLDER(folder), dest->path, &ok);
+ if (is_fatal(ok))
+ return -1;
statusbar_print_all(_("Adding messages..."));
total = g_slist_length(file_list);
for (cur = file_list; cur != NULL; cur = cur->next) {
@@ -1766,7 +1770,11 @@ static gint imap_do_copy_msgs(Folder *folder, FolderItem *dest,
unlock_session(session);
- destdir = imap_get_real_path(session, IMAP_FOLDER(folder), dest->path);
+ destdir = imap_get_real_path(session, IMAP_FOLDER(folder), dest->path, &ok);
+
+ if (is_fatal(ok))
+ return ok;
+
seq_list = imap_get_lep_set_from_msglist(IMAP_FOLDER(folder), msglist);
uid_mapping = g_relation_new(2);
g_relation_index(uid_mapping, 0, g_direct_hash, g_direct_equal);
@@ -1946,7 +1954,9 @@ static gint imap_do_remove_msgs(Folder *folder, FolderItem *dest,
return ok;
}
- destdir = imap_get_real_path(session, IMAP_FOLDER(folder), dest->path);
+ destdir = imap_get_real_path(session, IMAP_FOLDER(folder), dest->path, &ok);
+ if (is_fatal(ok))
+ return ok;
for (cur = msglist; cur; cur = cur->next) {
msginfo = (MsgInfo *)cur->data;
if (!MSG_IS_DELETED(msginfo->flags))
@@ -2061,11 +2071,15 @@ static gint imap_scan_tree_real(Folder *folder, gboolean subs_only)
extract_quote(root_folder, '"');
subst_char(root_folder,
imap_get_path_separator(session, IMAP_FOLDER(folder),
- root_folder),
+ root_folder, &r),
'/');
+ if (is_fatal(r))
+ return -1;
strtailchomp(root_folder, '/');
real_path = imap_get_real_path
- (session, IMAP_FOLDER(folder), root_folder);
+ (session, IMAP_FOLDER(folder), root_folder, &r);
+ if (is_fatal(r))
+ return -1;
debug_print("IMAP root directory: %s\n", real_path);
/* check if root directory exist */
@@ -2141,7 +2155,9 @@ static gint imap_scan_tree_recursive(IMAPSession *session, FolderItem *item, gbo
folder = item->folder;
imapfolder = IMAP_FOLDER(folder);
- separator = imap_get_path_separator(session, imapfolder, item->path);
+ separator = imap_get_path_separator(session, imapfolder, item->path, &r);
+ if (is_fatal(r))
+ return r;
if (folder->ui_func)
folder->ui_func(folder, item, folder->ui_func_data);
@@ -2150,7 +2166,9 @@ static gint imap_scan_tree_recursive(IMAPSession *session, FolderItem *item, gbo
wildcard[0] = separator;
wildcard[1] = '%';
wildcard[2] = '\0';
- real_path = imap_get_real_path(session, imapfolder, item->path);
+ real_path = imap_get_real_path(session, imapfolder, item->path, &r);
+ if (is_fatal(r))
+ return r;
} else {
wildcard[0] = '%';
wildcard[1] = '\0';
@@ -2169,6 +2187,7 @@ static gint imap_scan_tree_recursive(IMAPSession *session, FolderItem *item, gbo
if (r != MAILIMAP_NO_ERROR) {
imap_handle_error(SESSION(session), r);
item_list = NULL;
+ return r;
}
else {
item_list = imap_list_from_lep(imapfolder,
@@ -2282,13 +2301,17 @@ GList *imap_scan_subtree(Folder *folder, FolderItem *item, gboolean unsubs_only,
if (!session)
return NULL;
- separator = imap_get_path_separator(session, IMAP_FOLDER(folder), item->path);
+ separator = imap_get_path_separator(session, IMAP_FOLDER(folder), item->path, &r);
+ if (is_fatal(r))
+ return NULL;
if (item->path) {
wildcard[0] = separator;
wildcard[1] = '%';
wildcard[2] = '\0';
- real_path = imap_get_real_path(session, IMAP_FOLDER(folder), item->path);
+ real_path = imap_get_real_path(session, IMAP_FOLDER(folder), item->path, &r);
+ if (is_fatal(r))
+ return NULL;
} else {
wildcard[0] = '%';
wildcard[1] = '\0';
@@ -2325,8 +2348,11 @@ GList *imap_scan_subtree(Folder *folder, FolderItem *item, gboolean unsubs_only,
}
child_list = g_list_prepend(child_list,
imap_get_real_path(session,
- IMAP_FOLDER(folder), cur_item->path));
-
+ IMAP_FOLDER(folder), cur_item->path, &r));
+ if (is_fatal(r)) {
+ statusbar_pop_all();
+ return NULL;
+ }
folder_item_destroy(cur_item);
}
child_list = g_list_reverse(child_list);
@@ -2346,7 +2372,11 @@ GList *imap_scan_subtree(Folder *folder, FolderItem *item, gboolean unsubs_only,
FolderItem *cur_item = FOLDER_ITEM(cur->data);
GList *oldlitem = NULL;
gchar *tmp = imap_get_real_path(session,
- IMAP_FOLDER(folder), cur_item->path);
+ IMAP_FOLDER(folder), cur_item->path, &r);
+ if (r) {
+ statusbar_pop_all();
+ return NULL;
+ }
folder_item_destroy(cur_item);
oldlitem = g_list_find_custom(
child_list, tmp, (GCompareFunc)strcmp2);
@@ -2525,7 +2555,9 @@ static FolderItem *imap_create_folder(Folder *folder, FolderItem *parent,
g_free(dirpath);
return NULL;});
- separator = imap_get_path_separator(session, IMAP_FOLDER(folder), imap_path);
+ separator = imap_get_path_separator(session, IMAP_FOLDER(folder), imap_path, &ok);
+ if (is_fatal(ok))
+ return NULL;
imap_path_separator_subst(imap_path, separator);
/* remove trailing / for display */
strtailchomp(new_name, '/');
@@ -2643,13 +2675,17 @@ static gint imap_rename_folder(Folder *folder, FolderItem *item,
return -1;
}
- if (strchr(name, imap_get_path_separator(session, IMAP_FOLDER(folder), item->path)) != NULL) {
+ if (strchr(name, imap_get_path_separator(session, IMAP_FOLDER(folder), item->path, &ok)) != NULL ||
+ is_fatal(ok)) {
g_warning(_("New folder name must not contain the namespace "
"path separator"));
return -1;
}
- real_oldpath = imap_get_real_path(session, IMAP_FOLDER(folder), item->path);
+ real_oldpath = imap_get_real_path(session, IMAP_FOLDER(folder), item->path, &ok);
+ if (is_fatal(ok)) {
+ return -1;
+ }
g_free(session->mbox);
session->mbox = NULL;
@@ -2663,7 +2699,9 @@ static gint imap_rename_folder(Folder *folder, FolderItem *item,
return -1;
}
- separator = imap_get_path_separator(session, IMAP_FOLDER(folder), item->path);
+ separator = imap_get_path_separator(session, IMAP_FOLDER(folder), item->path, &ok);
+ if (is_fatal(ok))
+ return -1;
if (strchr(item->path, G_DIR_SEPARATOR)) {
dirpath = g_path_get_dirname(item->path);
newpath = g_strconcat(dirpath, G_DIR_SEPARATOR_S, name, NULL);
@@ -2721,8 +2759,8 @@ gint imap_subscribe(Folder *folder, FolderItem *item, gchar *rpath, gboolean sub
return -1;
}
if (item && item->path) {
- path = imap_get_real_path(session, IMAP_FOLDER(folder), item->path);
- if (!path)
+ path = imap_get_real_path(session, IMAP_FOLDER(folder), item->path, &r);
+ if (!path || is_fatal(r))
return -1;
if (!strcmp(path, "INBOX") && sub == FALSE)
return -1;
@@ -2753,7 +2791,9 @@ static gint imap_remove_folder_real(Folder *folder, FolderItem *item)
if (!session) {
return -1;
}
- path = imap_get_real_path(session, IMAP_FOLDER(folder), item->path);
+ path = imap_get_real_path(session, IMAP_FOLDER(folder), item->path, &ok);
+ if (is_fatal(ok))
+ return -1;
imap_threaded_subscribe(folder, path, FALSE);
@@ -2763,17 +2803,17 @@ static gint imap_remove_folder_real(Folder *folder, FolderItem *item)
ok = imap_cmd_close(session);
if (ok != MAILIMAP_NO_ERROR) {
debug_print("close err %d\n", ok);
- imap_handle_error(SESSION(session), ok);
return ok;
}
}
ok = imap_cmd_delete(session, path);
- if (ok != MAILIMAP_NO_ERROR) {
+ if (ok != MAILIMAP_NO_ERROR && !is_fatal(ok)) {
gchar *tmp = g_strdup_printf("%s%c", path,
- imap_get_path_separator(session, IMAP_FOLDER(folder), path));
+ imap_get_path_separator(session, IMAP_FOLDER(folder), path, &ok));
g_free(path);
path = tmp;
- ok = imap_cmd_delete(session, path);
+ if (!is_fatal(ok))
+ ok = imap_cmd_delete(session, path);
}
if (ok != MAILIMAP_NO_ERROR) {
@@ -3037,7 +3077,7 @@ gchar imap_get_path_separator_for_item(FolderItem *item)
IMAPFolder *imap_folder = NULL;
IMAPSession *session = NULL;
gchar result = '/';
-
+ gint ok;
if (!item)
return '/';
folder = item->folder;
@@ -3052,11 +3092,11 @@ gchar imap_get_path_separator_for_item(FolderItem *item)
debug_print("getting session...");
session = imap_session_get(FOLDER(folder));
- result = imap_get_path_separator(session, imap_folder, item->path);
+ result = imap_get_path_separator(session, imap_folder, item->path, &ok);
return result;
}
-static gchar imap_refresh_path_separator(IMAPSession *session, IMAPFolder *folder, const gchar *subfolder)
+static gchar imap_refresh_path_separator(IMAPSession *session, IMAPFolder *folder, const gchar *subfolder, gint *ok)
{
clist * lep_list;
int r;
@@ -3068,6 +3108,7 @@ static gchar imap_refresh_path_separator(IMAPSession *session, IMAPFolder *folde
if (r != MAILIMAP_NO_ERROR) {
imap_handle_error(SESSION(session), r);
log_warning(LOG_PROTOCOL, _("LIST failed\n"));
+ *ok = r;
return '\0';
}
@@ -3079,20 +3120,21 @@ static gchar imap_refresh_path_separator(IMAPSession *session, IMAPFolder *folde
separator = mb->mb_delimiter;
debug_print("got separator: %c\n", folder->last_seen_separator);
}
+ *ok = MAILIMAP_NO_ERROR;
mailimap_list_result_free(lep_list);
return separator;
}
-static gchar imap_get_path_separator(IMAPSession *session, IMAPFolder *folder, const gchar *path)
+static gchar imap_get_path_separator(IMAPSession *session, IMAPFolder *folder, const gchar *path, gint *ok)
{
gchar separator = '/';
if (folder->last_seen_separator == 0) {
- folder->last_seen_separator = imap_refresh_path_separator(session, folder, "");
+ folder->last_seen_separator = imap_refresh_path_separator(session, folder, "", ok);
}
if (folder->last_seen_separator == 0) {
- folder->last_seen_separator = imap_refresh_path_separator(session, folder, "INBOX");
+ folder->last_seen_separator = imap_refresh_path_separator(session, folder, "INBOX", ok);
}
if (folder->last_seen_separator != 0) {
@@ -3103,7 +3145,7 @@ static gchar imap_get_path_separator(IMAPSession *session, IMAPFolder *folder, c
return separator;
}
-static gchar *imap_get_real_path(IMAPSession *session, IMAPFolder *folder, const gchar *path)
+static gchar *imap_get_real_path(IMAPSession *session, IMAPFolder *folder, const gchar *path, gint *ok)
{
gchar *real_path;
gchar separator;
@@ -3112,7 +3154,7 @@ static gchar *imap_get_real_path(IMAPSession *session, IMAPFolder *folder, const
g_return_val_if_fail(path != NULL, NULL);
real_path = imap_utf8_to_modified_utf7(path, FALSE);
- separator = imap_get_path_separator(session, folder, path);
+ separator = imap_get_path_separator(session, folder, path, ok);
imap_path_separator_subst(real_path, separator);
return real_path;
@@ -3232,8 +3274,9 @@ static gint imap_select(IMAPSession *session, IMAPFolder *folder,
session->recent = 0;
session->expunge = 0;
- real_path = imap_get_real_path(session, folder, path);
-
+ real_path = imap_get_real_path(session, folder, path, &ok);
+ if (is_fatal(ok))
+ return ok;
g_slist_free(IMAP_FOLDER_ITEM(item)->ok_flags);
IMAP_FOLDER_ITEM(item)->ok_flags = NULL;
ok = imap_cmd_select(session, real_path,
@@ -3276,7 +3319,9 @@ static gint imap_status(IMAPSession *session, IMAPFolder *folder,
gchar *real_path;
guint mask = 0;
- real_path = imap_get_real_path(session, folder, path);
+ real_path = imap_get_real_path(session, folder, path, &r);
+ if (is_fatal(r))
+ return r;
if (messages) {
mask |= 1 << 0;
@@ -3299,7 +3344,6 @@ static gint imap_status(IMAPSession *session, IMAPFolder *folder,
!strcmp(session->mbox, item->item.path)) {
r = imap_cmd_close(session);
if (r != MAILIMAP_NO_ERROR) {
- imap_handle_error(SESSION(session), r);
debug_print("close err %d\n", r);
return r;
}
@@ -3545,7 +3589,6 @@ static gint imap_cmd_create(IMAPSession *session, const gchar *folder)
r = imap_threaded_create(session->folder, folder);
if (r != MAILIMAP_NO_ERROR) {
imap_handle_error(SESSION(session), r);
-
return r;
}
@@ -3609,7 +3652,7 @@ static void *imap_cmd_fetch_thread(void *data)
if (r != MAILIMAP_NO_ERROR) {
imap_handle_error(SESSION(session), r);
debug_print("fetch err %d\n", r);
- return GINT_TO_POINTER(MAILIMAP_ERROR_BAD_STATE);
+ return GINT_TO_POINTER(r);
}
return GINT_TO_POINTER(MAILIMAP_NO_ERROR);
}
@@ -3765,7 +3808,7 @@ static gboolean imap_rename_folder_func(GNode *node, gpointer data)
gchar *new_itempath;
gint oldpathlen;
IMAPSession *session = imap_session_get(item->folder);
-
+ gint ok;
oldpathlen = strlen(oldpath);
if (strncmp(oldpath, item->path, oldpathlen) != 0) {
g_warning("path doesn't match: %s, %s\n", oldpath, item->path);
@@ -3780,11 +3823,11 @@ static gboolean imap_rename_folder_func(GNode *node, gpointer data)
new_itempath = g_strconcat(newpath, G_DIR_SEPARATOR_S, base,
NULL);
- real_oldpath = imap_get_real_path(session, IMAP_FOLDER(item->folder), item->path);
+ real_oldpath = imap_get_real_path(session, IMAP_FOLDER(item->folder), item->path, &ok);
g_free(item->path);
item->path = new_itempath;
- real_newpath = imap_get_real_path(session, IMAP_FOLDER(item->folder), item->path);
+ real_newpath = imap_get_real_path(session, IMAP_FOLDER(item->folder), item->path, &ok);
imap_threaded_subscribe(item->folder, real_oldpath, FALSE);
imap_threaded_subscribe(item->folder, real_newpath, TRUE);