diff --git a/changes/bug27893 b/changes/bug27893 new file mode 100644 index 0000000000..98b0f558cb --- /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 91e2758650..b8cb50340f 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 045cbc94fe..35897935f3 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 aebd035c56..efaa3e480a 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 510b8964b2..8a8b7ced01 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 state is reasonable, and a * permissible transition from old_state. 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 55936a7367..38c7fd76d0 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