Fix use after free
[claws.git] / src / msgcache.c
index e7bf1886a5882258462d49fbabe8482f84f8ab1a..82480ed9c10b7d02babd720098ac9633860599e9 100644 (file)
@@ -19,6 +19,7 @@
 
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
+#include "claws-features.h"
 #endif
 
 #include "defs.h"
@@ -186,10 +187,12 @@ void msgcache_remove_msg(MsgCache *cache, guint msgnum)
        if(msginfo->msgid)
                g_hash_table_remove(cache->msgid_table, msginfo->msgid);
        g_hash_table_remove(cache->msgnum_table, &msginfo->msgnum);
+
+       msginfo->folder->cache_dirty = TRUE;
+
        procmsg_msginfo_free(msginfo);
        cache->last_access = time(NULL);
 
-       msginfo->folder->cache_dirty = TRUE;
 
        debug_print("Cache size: %d messages, %u bytes\n", g_hash_table_size(cache->msgnum_table), cache->memusage);
 }
@@ -713,12 +716,6 @@ MsgCache *msgcache_read_cache(FolderItem *item, const gchar *cache_file)
                        if(msginfo->msgid)
                                g_hash_table_insert(cache->msgid_table, msginfo->msgid, msginfo);
                }
-
-#ifdef G_OS_WIN32
-               UnmapViewOfFile((void*) cache_data);
-#else
-               munmap(cache_data, map_len);
-#endif
        } else {
                while (fread(&num, sizeof(num), 1, fp) == 1) {
                        if (swapping)
@@ -771,8 +768,14 @@ MsgCache *msgcache_read_cache(FolderItem *item, const gchar *cache_file)
                }
        }
 bail_err:
+       if (cache_data != NULL && cache_data != MAP_FAILED) {
+#ifdef G_OS_WIN32
+               UnmapViewOfFile((void*) cache_data);
+#else
+               munmap(cache_data, map_len);
+#endif
+       }
        fclose(fp);
-
        if (conv != NULL) {
                if (conv->free != NULL)
                        conv->free(conv);
@@ -802,7 +805,7 @@ void msgcache_read_mark(MsgCache *cache, const gchar *mark_file)
        gint map_len = -1;
        char *cache_data = NULL;
        struct stat st;
-       gboolean error;
+       gboolean error = FALSE;
 
        swapping = TRUE;
 
@@ -858,16 +861,14 @@ void msgcache_read_mark(MsgCache *cache, const gchar *mark_file)
                                msginfo->flags.perm_flags = perm_flags;
                        }
                }
-#ifdef G_OS_WIN32
-               UnmapViewOfFile((void*) cache_data);
-#else
-               munmap(cache_data, map_len);
-#endif
        } else {
                while (fread(&num, sizeof(num), 1, fp) == 1) {
                        if (swapping)
                                num = bswap_32(num);
-                       if (fread(&perm_flags, sizeof(perm_flags), 1, fp) != 1) break;
+                       if (fread(&perm_flags, sizeof(perm_flags), 1, fp) != 1) {
+                               error = TRUE;
+                               break;
+                       }
                        if (swapping)
                                perm_flags = bswap_32(perm_flags);
                        msginfo = g_hash_table_lookup(cache->msgnum_table, &num);
@@ -877,7 +878,17 @@ void msgcache_read_mark(MsgCache *cache, const gchar *mark_file)
                }       
        }
 bail_err:
+       if (cache_data != NULL && cache_data != MAP_FAILED) {
+#ifdef G_OS_WIN32
+               UnmapViewOfFile((void*) cache_data);
+#else
+               munmap(cache_data, map_len);
+#endif
+       }
        fclose(fp);
+       if (error) {
+               debug_print("error reading cache mark from %s\n", mark_file);
+       }
 }
 
 void msgcache_read_tags(MsgCache *cache, const gchar *tags_file)
@@ -954,11 +965,6 @@ void msgcache_read_tags(MsgCache *cache, const gchar *tags_file)
                                msginfo->tags = g_slist_reverse(msginfo->tags);
                        }
                }
-#ifdef G_OS_WIN32
-               UnmapViewOfFile((void*) cache_data);
-#else
-               munmap(cache_data, map_len);
-#endif
        } else {
                while (fread(&num, sizeof(num), 1, fp) == 1) {
                        gint id = -1;
@@ -984,7 +990,17 @@ void msgcache_read_tags(MsgCache *cache, const gchar *tags_file)
                }
        }
 bail_err:
+       if (cache_data != NULL && cache_data != MAP_FAILED) {
+#ifdef G_OS_WIN32
+               UnmapViewOfFile((void*) cache_data);
+#else
+               munmap(cache_data, map_len);
+#endif
+       }
        fclose(fp);
+       if (error) {
+               debug_print("error reading cache tags from %s\n", tags_file);
+       }
 }
 
 static int msgcache_write_cache(MsgInfo *msginfo, FILE *fp)
@@ -1126,7 +1142,8 @@ gint msgcache_write(const gchar *cache_file, const gchar *mark_file, const gchar
 
        if (w_err != 0) {
                g_warning("failed to write charset\n");
-               fclose(write_fps.cache_fp);
+               if (write_fps.cache_fp)
+                       fclose(write_fps.cache_fp);
                claws_unlink(new_cache);
                g_free(new_cache);
                g_free(new_mark);
@@ -1138,7 +1155,8 @@ gint msgcache_write(const gchar *cache_file, const gchar *mark_file, const gchar
                write_fps.mark_fp = msgcache_open_data_file(new_mark, MARK_VERSION,
                        DATA_WRITE, NULL, 0);
                if (write_fps.mark_fp == NULL) {
-                       fclose(write_fps.cache_fp);
+                       if (write_fps.cache_fp)
+                               fclose(write_fps.cache_fp);
                        claws_unlink(new_cache);
                        g_free(new_cache);
                        g_free(new_mark);
@@ -1153,8 +1171,10 @@ gint msgcache_write(const gchar *cache_file, const gchar *mark_file, const gchar
                write_fps.tags_fp = msgcache_open_data_file(new_tags, TAGS_VERSION,
                        DATA_WRITE, NULL, 0);
                if (write_fps.tags_fp == NULL) {
-                       fclose(write_fps.cache_fp);
-                       fclose(write_fps.mark_fp);
+                       if (write_fps.cache_fp)
+                               fclose(write_fps.cache_fp);
+                       if (write_fps.mark_fp)
+                               fclose(write_fps.mark_fp);
                        claws_unlink(new_cache);
                        claws_unlink(new_mark);
                        g_free(new_cache);