[tor-commits] [tor/master] Switch to a safer FREE_AND_NULL implementation

nickm at torproject.org nickm at torproject.org
Fri Dec 8 20:04:29 UTC 2017


commit db024adc90069ce9961f3993aba1b7372f09d77a
Author: Nick Mathewson <nickm at torproject.org>
Date:   Mon Dec 4 15:09:18 2017 -0500

    Switch to a safer FREE_AND_NULL implementation
    
    This one only evaluates the input once, so it cannot mess up even if
    there are side effects.
---
 src/common/address.h         |  2 +-
 src/common/aes.h             |  3 ++-
 src/common/compat_libevent.h |  3 ++-
 src/common/compress.h        |  3 ++-
 src/common/compress_lzma.h   |  4 +++-
 src/common/compress_zlib.h   |  4 +++-
 src/common/compress_zstd.h   |  4 +++-
 src/common/log.c             |  2 +-
 src/common/timers.h          |  2 +-
 src/common/util.h            | 21 ++++++++++++++++-----
 src/or/hs_service.c          |  2 +-
 src/or/hs_service.h          |  9 ++++++---
 src/or/networkstatus.h       |  3 ++-
 src/or/policies.h            |  3 ++-
 src/or/rendcache.c           |  6 +++---
 src/or/rendcache.h           | 10 ++++++----
 src/or/rendservice.c         |  6 +++---
 src/or/router.h              |  3 ++-
 src/or/routerlist.c          |  2 +-
 src/or/shared_random_state.c |  2 +-
 src/test/test.c              |  2 +-
 src/test/test_dir.c          |  2 +-
 22 files changed, 63 insertions(+), 35 deletions(-)

diff --git a/src/common/address.h b/src/common/address.h
index 84d136d67..6f59e1c96 100644
--- a/src/common/address.h
+++ b/src/common/address.h
@@ -208,7 +208,7 @@ MOCK_DECL(int,get_interface_address6,(int severity, sa_family_t family,
 tor_addr_t *addr));
 void interface_address6_list_free_(smartlist_t * addrs);// XXXX
 #define interface_address6_list_free(addrs) \
-  FREE_AND_NULL(interface_address6_list, (addrs))
+  FREE_AND_NULL_UNMATCHED(smartlist_t, interface_address6_list_free_, (addrs))
 MOCK_DECL(smartlist_t *,get_interface_address6_list,(int severity,
                                                      sa_family_t family,
                                                      int include_internal));
diff --git a/src/common/aes.h b/src/common/aes.h
index 4874f728d..c2720d29b 100644
--- a/src/common/aes.h
+++ b/src/common/aes.h
@@ -18,7 +18,8 @@ typedef struct aes_cnt_cipher aes_cnt_cipher_t;
 aes_cnt_cipher_t* aes_new_cipher(const uint8_t *key, const uint8_t *iv,
                                  int key_bits);
 void aes_cipher_free_(aes_cnt_cipher_t *cipher);
-#define aes_cipher_free(cipher) FREE_AND_NULL(aes_cipher, (cipher))
+#define aes_cipher_free(cipher) \
+  FREE_AND_NULL_UNMATCHED(aes_cnt_cipher_t, aes_cipher_free_, (cipher))
 void aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len);
 
 int evaluate_evp_for_aes(int force_value);
diff --git a/src/common/compat_libevent.h b/src/common/compat_libevent.h
index 65807315c..2c86194d0 100644
--- a/src/common/compat_libevent.h
+++ b/src/common/compat_libevent.h
@@ -20,7 +20,8 @@ void suppress_libevent_log_msg(const char *msg);
   (sock),(tcp),(cb),(data));
 
 void tor_event_free_(struct event *ev);
-#define tor_event_free(ev) FREE_AND_NULL(tor_event, (ev))
+#define tor_event_free(ev) \
+  FREE_AND_NULL_UNMATCHED(struct event, tor_event_free_, (ev))
 
 typedef struct periodic_timer_t periodic_timer_t;
 
diff --git a/src/common/compress.h b/src/common/compress.h
index eee4a315d..7420f169f 100644
--- a/src/common/compress.h
+++ b/src/common/compress.h
@@ -81,7 +81,8 @@ tor_compress_output_t tor_compress_process(tor_compress_state_t *state,
                                            const char **in, size_t *in_len,
                                            int finish);
 void tor_compress_free_(tor_compress_state_t *state);
-#define tor_compress_free(st) FREE_AND_NULL(tor_compress, (st))
+#define tor_compress_free(st) \
+  FREE_AND_NULL_UNMATCHED(tor_compress_state_t, tor_compress_free_, (st))
 
 size_t tor_compress_state_size(const tor_compress_state_t *state);
 
diff --git a/src/common/compress_lzma.h b/src/common/compress_lzma.h
index 1e92fd660..986bfe9a6 100644
--- a/src/common/compress_lzma.h
+++ b/src/common/compress_lzma.h
@@ -32,7 +32,9 @@ tor_lzma_compress_process(tor_lzma_compress_state_t *state,
                           int finish);
 
 void tor_lzma_compress_free_(tor_lzma_compress_state_t *state);
-#define tor_lzma_compress_free(st) FREE_AND_NULL(tor_lzma_compress, (st))
+#define tor_lzma_compress_free(st)                      \
+  FREE_AND_NULL_UNMATCHED(tor_lzma_compress_state_t,   \
+                           tor_lzma_compress_free_, (st))
 
 size_t tor_lzma_compress_state_size(const tor_lzma_compress_state_t *state);
 
diff --git a/src/common/compress_zlib.h b/src/common/compress_zlib.h
index 3377e0e8d..701e2f9e8 100644
--- a/src/common/compress_zlib.h
+++ b/src/common/compress_zlib.h
@@ -32,7 +32,9 @@ tor_zlib_compress_process(tor_zlib_compress_state_t *state,
                           int finish);
 
 void tor_zlib_compress_free_(tor_zlib_compress_state_t *state);
-#define tor_zlib_compress_free(st) FREE_AND_NULL(tor_zlib_compress, (st))
+#define tor_zlib_compress_free(st)                      \
+  FREE_AND_NULL_UNMATCHED(tor_zlib_compress_state_t,   \
+                           tor_zlib_compress_free_, (st))
 
 size_t tor_zlib_compress_state_size(const tor_zlib_compress_state_t *state);
 
diff --git a/src/common/compress_zstd.h b/src/common/compress_zstd.h
index 9f67a9c58..3e18febb1 100644
--- a/src/common/compress_zstd.h
+++ b/src/common/compress_zstd.h
@@ -32,7 +32,9 @@ tor_zstd_compress_process(tor_zstd_compress_state_t *state,
                           int finish);
 
 void tor_zstd_compress_free_(tor_zstd_compress_state_t *state);
-#define tor_zstd_compress_free(st) FREE_AND_NULL(tor_zstd_compress, (st))
+#define tor_zstd_compress_free(st)                      \
+  FREE_AND_NULL_UNMATCHED(tor_zstd_compress_state_t,   \
+                           tor_zstd_compress_free_, (st))
 
 size_t tor_zstd_compress_state_size(const tor_zstd_compress_state_t *state);
 
diff --git a/src/common/log.c b/src/common/log.c
index 83098b101..d305c9ae5 100644
--- a/src/common/log.c
+++ b/src/common/log.c
@@ -65,7 +65,7 @@ typedef struct logfile_t {
 
 static void log_free_(logfile_t *victim);
 #define log_free(lg)    \
-  FREE_AND_NULL(log, (lg))
+  FREE_AND_NULL_UNMATCHED(logfile_t, log_free_, (lg))
 
 /** Helper: map a log severity to descriptive string. */
 static inline const char *
diff --git a/src/common/timers.h b/src/common/timers.h
index 6c9594d31..86e892016 100644
--- a/src/common/timers.h
+++ b/src/common/timers.h
@@ -18,7 +18,7 @@ void timer_get_cb(const tor_timer_t *t,
 void timer_schedule(tor_timer_t *t, const struct timeval *delay);
 void timer_disable(tor_timer_t *t);
 void timer_free_(tor_timer_t *t);
-#define timer_free(t) FREE_AND_NULL(timer, (t))
+#define timer_free(t) FREE_AND_NULL_UNMATCHED(tor_timer_t, timer_free_, (t))
 
 void timers_initialize(void);
 void timers_shutdown(void);
diff --git a/src/common/util.h b/src/common/util.h
index c5bd3f0bd..9ed11260d 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -109,13 +109,24 @@ extern int dmalloc_free(const char *file, const int line, void *pnt,
 
 void tor_log_mallinfo(int severity);
 
+/* Helper macro: free a variable of type 'typename' using freefn, and
+ * set the variable to NULL.
+ *
+ * We use this for legacy cases when freefn and typename don't line up
+ * perfectly.
+ */
+#define FREE_AND_NULL_UNMATCHED(typename, freefn, var)                  \
+  do {                                                                  \
+    /* only evaluate (var) once. */                                     \
+    typename **tmp__free__ptr ## freefn = &(var);                       \
+    freefn(*tmp__free__ptr ## freefn);                                  \
+    (*tmp__free__ptr ## freefn) = NULL;                                 \
+  } while (0)
+
 /* Helper macro: free a variable of type 'type' using type_free_, and
  * set the variable to NULL. */
-#define FREE_AND_NULL(type, var)                                \
-  do {                                                          \
-      type ## _free_(var);                                      \
-      (var) = NULL;                                             \
-  } while (0)
+#define FREE_AND_NULL(type, var)                                        \
+  FREE_AND_NULL_UNMATCHED(type ## _t, type ## _free_, (var))
 
 /** Macro: yield a pointer to the field at position <b>off</b> within the
  * structure <b>st</b>.  Example:
diff --git a/src/or/hs_service.c b/src/or/hs_service.c
index e88fb2389..1f93c2d52 100644
--- a/src/or/hs_service.c
+++ b/src/or/hs_service.c
@@ -370,7 +370,7 @@ service_intro_point_free_(hs_service_intro_point_t *ip)
 static void
 service_intro_point_free_void(void *obj)
 {
-  service_intro_point_free(obj);
+  service_intro_point_free_(obj);
 }
 
 /* Return a newly allocated service intro point and fully initialized from the
diff --git a/src/or/hs_service.h b/src/or/hs_service.h
index b75903016..f933ba6ab 100644
--- a/src/or/hs_service.h
+++ b/src/or/hs_service.h
@@ -295,8 +295,9 @@ STATIC hs_service_intro_point_t *service_intro_point_new(
                                          const extend_info_t *ei,
                                          unsigned int is_legacy);
 STATIC void service_intro_point_free_(hs_service_intro_point_t *ip);
-#define service_intro_point_free(ip)            \
-  FREE_AND_NULL(service_intro_point, (ip))
+#define service_intro_point_free(ip)                            \
+  FREE_AND_NULL_UNMATCHED(hs_service_intro_point_t,             \
+                          service_intro_point_free_, (ip))
 STATIC void service_intro_point_add(digest256map_t *map,
                                     hs_service_intro_point_t *ip);
 STATIC void service_intro_point_remove(const hs_service_t *service,
@@ -330,7 +331,9 @@ STATIC char *
 encode_desc_rev_counter_for_state(const hs_service_descriptor_t *desc);
 
 STATIC void service_descriptor_free_(hs_service_descriptor_t *desc);
-#define service_descriptor_free(d) FREE_AND_NULL(service_descriptor, (d))
+#define service_descriptor_free(d) \
+  FREE_AND_NULL_UNMATCHED(hs_service_descriptor_t, \
+                           service_descriptor_free_, (d))
 
 STATIC uint64_t
 check_state_line_for_service_rev_counter(const char *state_line,
diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h
index f62b5d240..37350bb1b 100644
--- a/src/or/networkstatus.h
+++ b/src/or/networkstatus.h
@@ -21,7 +21,8 @@ int router_reload_consensus_networkstatus(void);
 void routerstatus_free_(routerstatus_t *rs);
 #define routerstatus_free(rs) FREE_AND_NULL(routerstatus, (rs))
 void networkstatus_vote_free_(networkstatus_t *ns);
-#define networkstatus_vote_free(ns) FREE_AND_NULL(networkstatus_vote, (ns))
+#define networkstatus_vote_free(ns) \
+  FREE_AND_NULL_UNMATCHED(networkstatus_t, networkstatus_vote_free_, (ns))
 networkstatus_voter_info_t *networkstatus_get_voter_by_id(
                                        networkstatus_t *vote,
                                        const char *identity);
diff --git a/src/or/policies.h b/src/or/policies.h
index 062f33018..451a7a7f3 100644
--- a/src/or/policies.h
+++ b/src/or/policies.h
@@ -116,7 +116,8 @@ int policy_write_item(char *buf, size_t buflen, const addr_policy_t *item,
                       int format_for_desc);
 
 void addr_policy_list_free_(smartlist_t *p);
-#define addr_policy_list_free(lst) FREE_AND_NULL(addr_policy_list, (lst))
+#define addr_policy_list_free(lst) \
+  FREE_AND_NULL_UNMATCHED(smartlist_t, addr_policy_list_free_, (lst))
 void addr_policy_free_(addr_policy_t *p);
 #define addr_policy_free(p) FREE_AND_NULL(addr_policy, (p))
 void policies_free_all(void);
diff --git a/src/or/rendcache.c b/src/or/rendcache.c
index fa454321d..6f56df671 100644
--- a/src/or/rendcache.c
+++ b/src/or/rendcache.c
@@ -131,7 +131,7 @@ rend_cache_failure_intro_entry_free_(rend_cache_failure_intro_t *entry)
 static void
 rend_cache_failure_intro_entry_free_void(void *entry)
 {
-  rend_cache_failure_intro_entry_free(entry);
+  rend_cache_failure_intro_entry_free_(entry);
 }
 
 /** Allocate a rend cache failure intro object and return it. <b>failure</b>
@@ -165,7 +165,7 @@ rend_cache_failure_entry_free_(rend_cache_failure_t *entry)
 STATIC void
 rend_cache_failure_entry_free_void(void *entry)
 {
-  rend_cache_failure_entry_free(entry);
+  rend_cache_failure_entry_free_(entry);
 }
 
 /** Allocate a rend cache failure object and return it. This function can
@@ -219,7 +219,7 @@ rend_cache_entry_free_(rend_cache_entry_t *e)
 static void
 rend_cache_entry_free_void(void *p)
 {
-  rend_cache_entry_free(p);
+  rend_cache_entry_free_(p);
 }
 
 /** Free all storage held by the service descriptor cache. */
diff --git a/src/or/rendcache.h b/src/or/rendcache.h
index 66b48e032..c1e9207a9 100644
--- a/src/or/rendcache.h
+++ b/src/or/rendcache.h
@@ -94,11 +94,13 @@ STATIC void rend_cache_entry_free_(rend_cache_entry_t *e);
 #define rend_cache_entry_free(e) FREE_AND_NULL(rend_cache_entry, (e))
 STATIC void rend_cache_failure_intro_entry_free_(rend_cache_failure_intro_t
                                                  *entry);
-#define rend_cache_failure_intro_entry_free(e) \
-  FREE_AND_NULL(rend_cache_failure_intro_entry, (e))
+#define rend_cache_failure_intro_entry_free(e)                          \
+  FREE_AND_NULL_UNMATCHED(rend_cache_failure_intro_t,                   \
+                          rend_cache_failure_intro_entry_free_, (e))
 STATIC void rend_cache_failure_entry_free_(rend_cache_failure_t *entry);
-#define rend_cache_failure_entry_free(e) \
-  FREE_AND_NULL(rend_cache_failure_entry, (e))
+#define rend_cache_failure_entry_free(e)                        \
+  FREE_AND_NULL_UNMATCHED(rend_cache_failure_t,                 \
+                          rend_cache_failure_entry_free_, (e))
 STATIC int cache_failure_intro_lookup(const uint8_t *identity,
                                       const char *service_id,
                                       rend_cache_failure_intro_t
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 568afe79b..3e318f73f 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -174,7 +174,7 @@ rend_authorized_client_free_(rend_authorized_client_t *client)
 static void
 rend_authorized_client_strmap_item_free(void *authorized_client)
 {
-  rend_authorized_client_free(authorized_client);
+  rend_authorized_client_free_(authorized_client);
 }
 
 /** Release the storage held by <b>service</b>.
@@ -3726,7 +3726,7 @@ upload_service_descriptor(rend_service_t *service)
       }
       /* Free memory for descriptors. */
       for (i = 0; i < smartlist_len(descs); i++)
-        rend_encoded_v2_service_descriptor_free(smartlist_get(descs, i));
+        rend_encoded_v2_service_descriptor_free_(smartlist_get(descs, i));
       smartlist_clear(descs);
       /* Update next upload time. */
       if (seconds_valid - REND_TIME_PERIOD_OVERLAPPING_V2_DESCS
@@ -3757,7 +3757,7 @@ upload_service_descriptor(rend_service_t *service)
         }
         /* Free memory for descriptors. */
         for (i = 0; i < smartlist_len(descs); i++)
-          rend_encoded_v2_service_descriptor_free(smartlist_get(descs, i));
+          rend_encoded_v2_service_descriptor_free_(smartlist_get(descs, i));
         smartlist_clear(descs);
       }
     }
diff --git a/src/or/router.h b/src/or/router.h
index cd953da7a..e282b9975 100644
--- a/src/or/router.h
+++ b/src/or/router.h
@@ -37,7 +37,8 @@ int get_onion_key_grace_period(void);
 
 di_digest256_map_t *construct_ntor_key_map(void);
 void ntor_key_map_free_(di_digest256_map_t *map);
-#define ntor_key_map_free(map) FREE_AND_NULL(ntor_key_map, (map))
+#define ntor_key_map_free(map) \
+  FREE_AND_NULL_UNMATCHED(di_digest256_map_t, ntor_key_map_free_, (map))
 
 int router_initialize_tls_context(void);
 int init_keys(void);
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 877479969..0236761eb 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -3268,7 +3268,7 @@ signed_descriptor_from_routerinfo(routerinfo_t *ri)
 static void
 extrainfo_free_void(void *e)
 {
-  extrainfo_free(e);
+  extrainfo_free_(e);
 }
 
 /** Free all storage held by a routerlist <b>rl</b>. */
diff --git a/src/or/shared_random_state.c b/src/or/shared_random_state.c
index ae904cfda..8c5a497bb 100644
--- a/src/or/shared_random_state.c
+++ b/src/or/shared_random_state.c
@@ -271,7 +271,7 @@ commit_add_to_state(sr_commit_t *commit, sr_state_t *state)
 static void
 commit_free_(void *p)
 {
-  sr_commit_free(p);
+  sr_commit_free_(p);
 }
 
 /* Free a state that was allocated with state_new(). */
diff --git a/src/test/test.c b/src/test/test.c
index 1c5b654df..c08967c02 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -616,7 +616,7 @@ test_rend_fns(void *arg)
  done:
   if (descs) {
     for (i = 0; i < smartlist_len(descs); i++)
-      rend_encoded_v2_service_descriptor_free(smartlist_get(descs, i));
+      rend_encoded_v2_service_descriptor_free_(smartlist_get(descs, i));
     smartlist_free(descs);
   }
   if (parsed)
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index 4cab307ce..35e4fb44c 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -567,7 +567,7 @@ test_dir_routerinfo_parsing(void *arg)
 static void
 routerinfo_free_wrapper_(void *arg)
 {
-  routerinfo_free(arg);
+  routerinfo_free_(arg);
 }
 
 static void





More information about the tor-commits mailing list