[tor-commits] [tor/master] Fix a memory leak in --dump-config

nickm at torproject.org nickm at torproject.org
Mon Oct 1 17:17:25 UTC 2018


commit 8812f562a03234723871b893f269db09e78654fc
Author: Nick Mathewson <nickm at torproject.org>
Date:   Thu Sep 27 13:05:19 2018 -0400

    Fix a memory leak in --dump-config
    
    When freeing a configuration object from confparse.c in
    dump_config(), we need to call the appropriate higher-level free
    function (like or_options_free()) and not just config_free().
    
    This only happens with options (since they're the one where
    options_validate allocates extra stuff) and only when running
    --dump-config with something other than minimal (since
    OPTIONS_DUMP_MINIMAL doesn't hit this code).
    
    Fixes bug 27893; bugfix on 0.3.2.1-alpha.
---
 changes/bug27893                          | 3 +++
 src/app/config/config.c                   | 9 +++++++++
 src/app/config/confparse.c                | 5 +++--
 src/app/config/confparse.h                | 4 ++++
 src/app/config/statefile.c                | 9 +++++++++
 src/feature/dirauth/shared_random_state.c | 8 ++++++++
 6 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/changes/bug27893 b/changes/bug27893
new file mode 100644
index 000000000..98b0f558c
--- /dev/null
+++ b/changes/bug27893
@@ -0,0 +1,3 @@
+  o Minor bugfixes (memory leaks):
+    - Fix a small memory leak when calling Tor with --dump-config.
+      Fixes bug 27893; bugfix on 0.3.2.1-alpha.
diff --git a/src/app/config/config.c b/src/app/config/config.c
index 91e275865..b8cb50340 100644
--- a/src/app/config/config.c
+++ b/src/app/config/config.c
@@ -824,6 +824,7 @@ static void config_maybe_load_geoip_files_(const or_options_t *options,
 static int options_validate_cb(void *old_options, void *options,
                                void *default_options,
                                int from_setconf, char **msg);
+static void options_free_cb(void *options);
 static void cleanup_protocol_warning_severity_level(void);
 static void set_protocol_warning_severity_level(int warning_severity);
 
@@ -839,6 +840,7 @@ STATIC config_format_t options_format = {
   option_deprecation_notes_,
   option_vars_,
   options_validate_cb,
+  options_free_cb,
   NULL
 };
 
@@ -3149,6 +3151,13 @@ options_validate_cb(void *old_options, void *options, void *default_options,
   return rv;
 }
 
+/** Callback to free an or_options_t */
+static void
+options_free_cb(void *options)
+{
+  or_options_free_(options);
+}
+
 #define REJECT(arg) \
   STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
 #if defined(__GNUC__) && __GNUC__ <= 3
diff --git a/src/app/config/confparse.c b/src/app/config/confparse.c
index 045cbc94f..35897935f 100644
--- a/src/app/config/confparse.c
+++ b/src/app/config/confparse.c
@@ -1009,8 +1009,9 @@ config_dump(const config_format_t *fmt, const void *default_options,
   result = smartlist_join_strings(elements, "", 0, NULL);
   SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
   smartlist_free(elements);
-  if (defaults_tmp)
-    config_free(fmt, defaults_tmp);
+  if (defaults_tmp) {
+    fmt->free_fn(defaults_tmp);
+  }
   return result;
 }
 
diff --git a/src/app/config/confparse.h b/src/app/config/confparse.h
index aebd035c5..efaa3e480 100644
--- a/src/app/config/confparse.h
+++ b/src/app/config/confparse.h
@@ -155,6 +155,9 @@ typedef struct config_var_t {
  * of arguments. */
 typedef int (*validate_fn_t)(void*,void*,void*,int,char**);
 
+/** Callback to free a configuration object. */
+typedef void (*free_cfg_fn_t)(void*);
+
 /** Information on the keys, value types, key-to-struct-member mappings,
  * variable descriptions, validation functions, and abbreviations for a
  * configuration or storage format. */
@@ -169,6 +172,7 @@ typedef struct config_format_t {
   config_var_t *vars; /**< List of variables we recognize, their default
                        * values, and where we stick them in the structure. */
   validate_fn_t validate_fn; /**< Function to validate config. */
+  free_cfg_fn_t free_fn; /**< Function to free the configuration. */
   /** If present, extra is a LINELIST variable for unrecognized
    * lines.  Otherwise, unrecognized lines are an error. */
   config_var_t *extra;
diff --git a/src/app/config/statefile.c b/src/app/config/statefile.c
index 510b8964b..8a8b7ced0 100644
--- a/src/app/config/statefile.c
+++ b/src/app/config/statefile.c
@@ -143,6 +143,8 @@ static int or_state_validate_cb(void *old_options, void *options,
                                 void *default_options,
                                 int from_setconf, char **msg);
 
+static void or_state_free_cb(void *state);
+
 /** Magic value for or_state_t. */
 #define OR_STATE_MAGIC 0x57A73f57
 
@@ -162,6 +164,7 @@ static const config_format_t state_format = {
   NULL,
   state_vars_,
   or_state_validate_cb,
+  or_state_free_cb,
   &state_extra_var,
 };
 
@@ -259,6 +262,12 @@ or_state_validate_cb(void *old_state, void *state, void *default_state,
   return or_state_validate(state, msg);
 }
 
+static void
+or_state_free_cb(void *state)
+{
+  or_state_free_(state);
+}
+
 /** Return 0 if every setting in <b>state</b> is reasonable, and a
  * permissible transition from <b>old_state</b>.  Else warn and return -1.
  * Should have no side effects, except for normalizing the contents of
diff --git a/src/feature/dirauth/shared_random_state.c b/src/feature/dirauth/shared_random_state.c
index 55936a736..38c7fd76d 100644
--- a/src/feature/dirauth/shared_random_state.c
+++ b/src/feature/dirauth/shared_random_state.c
@@ -63,6 +63,7 @@ DUMMY_TYPECHECK_INSTANCE(sr_disk_state_t);
 static int
 disk_state_validate_cb(void *old_state, void *state, void *default_state,
                        int from_setconf, char **msg);
+static void disk_state_free_cb(void *);
 
 /* Array of variables that are saved to disk as a persistent state. */
 static config_var_t state_vars[] = {
@@ -96,6 +97,7 @@ static const config_format_t state_format = {
   NULL,
   state_vars,
   disk_state_validate_cb,
+  disk_state_free_cb,
   &state_extra_var,
 };
 
@@ -342,6 +344,12 @@ disk_state_validate_cb(void *old_state, void *state, void *default_state,
   return 0;
 }
 
+static void
+disk_state_free_cb(void *state)
+{
+  disk_state_free_(state);
+}
+
 /* Parse the Commit line(s) in the disk state and translate them to the
  * the memory state. Return 0 on success else -1 on error. */
 static int





More information about the tor-commits mailing list