浏览代码

Avoid double-free on failure to dump_descriptor() a cached md

This is a fix for 10423, which was introducd in caa0d15c in 0.2.4.13-alpha.

Spotted by bobnomnom.
Nick Mathewson 10 年之前
父节点
当前提交
46b3b6208d
共有 2 个文件被更改,包括 26 次插入11 次删除
  1. 4 0
      changes/bug10423
  2. 22 11
      src/or/microdesc.c

+ 4 - 0
changes/bug10423

@@ -0,0 +1,4 @@
+  o Minor bugfixes:
+    - If we fail to dump a previously cached microdescriptor to disk, avoid
+      freeing duplicate data later on. Fix for bug 10423; bugfix on
+      0.2.4.13-alpha. Spotted by "bobnomnom".

+ 22 - 11
src/or/microdesc.c

@@ -407,6 +407,26 @@ should_rebuild_md_cache(microdesc_cache_t *cache)
     return 0;
 }
 
+/**
+ * Mark <b>md</b> as having no body, and release any storage previously held
+ * by its body.
+ */
+static void
+microdesc_wipe_body(microdesc_t *md)
+{
+  if (!md)
+    return;
+
+  if (md->saved_location != SAVED_IN_CACHE)
+    tor_free(md->body);
+
+  md->off = 0;
+  md->saved_location = SAVED_NOWHERE;
+  md->body = NULL;
+  md->bodylen = 0;
+  md->no_save = 1;
+}
+
 /** Regenerate the main cache file for <b>cache</b>, clear the journal file,
  * and update every microdesc_t in the cache with pointers to its new
  * location.  If <b>force</b> is true, do this unconditionally.  If
@@ -455,12 +475,7 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force)
 
     size = dump_microdescriptor(fd, md, &annotation_len);
     if (size < 0) {
-      if (md->saved_location != SAVED_IN_CACHE)
-        tor_free(md->body);
-      md->saved_location = SAVED_NOWHERE;
-      md->off = 0;
-      md->bodylen = 0;
-      md->no_save = 1;
+      microdesc_wipe_body(md);
 
       /* rewind, in case it was a partial write. */
       tor_fd_setpos(fd, off);
@@ -497,11 +512,7 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force)
     HT_FOREACH(mdp, microdesc_map, &cache->map) {
       microdesc_t *md = *mdp;
       if (md->saved_location == SAVED_IN_CACHE) {
-        md->off = 0;
-        md->saved_location = SAVED_NOWHERE;
-        md->body = NULL;
-        md->bodylen = 0;
-        md->no_save = 1;
+        microdesc_wipe_body(md);
       }
     }
     return -1;