dovecot-2.0: Fixed memory leak when parsing settings.
dovecot at dovecot.org
dovecot at dovecot.org
Mon Apr 5 23:06:23 EEST 2010
details: http://hg.dovecot.org/dovecot-2.0/rev/46d4f3264417
changeset: 11078:46d4f3264417
user: Timo Sirainen <tss at iki.fi>
date: Mon Apr 05 23:06:19 2010 +0300
description:
Fixed memory leak when parsing settings.
diffstat:
src/lib-master/master-service-settings-cache.c | 11 +++-
src/lib-master/master-service-settings-cache.h | 1 +
src/lib-master/master-service-settings.h | 2 +-
src/lib-settings/settings-parser.c | 82 +++++++++++++++++++++++++++
src/lib-settings/settings-parser.h | 6 ++
src/lib-storage/mail-storage-service.c | 88 ++---------------------------
src/login-common/login-settings.c | 2 +-
7 files changed, 107 insertions(+), 85 deletions(-)
diffs (truncated from 337 to 300 lines):
diff -r 8627be1f6de9 -r 46d4f3264417 src/lib-master/master-service-settings-cache.c
--- a/src/lib-master/master-service-settings-cache.c Mon Apr 05 11:04:20 2010 +0300
+++ b/src/lib-master/master-service-settings-cache.c Mon Apr 05 23:06:19 2010 +0300
@@ -253,10 +253,12 @@
int master_service_settings_cache_read(struct master_service_settings_cache *cache,
const struct master_service_settings_input *input,
+ const struct dynamic_settings_parser *dyn_parsers,
const struct setting_parser_context **parser_r,
const char **error_r)
{
struct master_service_settings_output output;
+ struct master_service_settings_input new_input;
const struct master_service_settings *set;
i_assert(null_strcmp(input->module, cache->module) == 0);
@@ -265,7 +267,12 @@
if (cache_find(cache, input, parser_r))
return 0;
- if (master_service_settings_read(cache->service, input,
+ new_input = *input;
+ if (dyn_parsers != NULL) {
+ settings_parser_dyn_update(cache->pool, &new_input.roots,
+ dyn_parsers);
+ }
+ if (master_service_settings_read(cache->service, &new_input,
&output, error_r) < 0)
return -1;
@@ -287,7 +294,7 @@
return -1;
}
- cache_add(cache, input, &output, cache->service->set_parser);
+ cache_add(cache, &new_input, &output, cache->service->set_parser);
*parser_r = cache->service->set_parser;
return 0;
}
diff -r 8627be1f6de9 -r 46d4f3264417 src/lib-master/master-service-settings-cache.h
--- a/src/lib-master/master-service-settings-cache.h Mon Apr 05 11:04:20 2010 +0300
+++ b/src/lib-master/master-service-settings-cache.h Mon Apr 05 23:06:19 2010 +0300
@@ -9,6 +9,7 @@
int master_service_settings_cache_read(struct master_service_settings_cache *cache,
const struct master_service_settings_input *input,
+ const struct dynamic_settings_parser *dyn_parsers,
const struct setting_parser_context **parser_r,
const char **error_r);
diff -r 8627be1f6de9 -r 46d4f3264417 src/lib-master/master-service-settings.h
--- a/src/lib-master/master-service-settings.h Mon Apr 05 11:04:20 2010 +0300
+++ b/src/lib-master/master-service-settings.h Mon Apr 05 23:06:19 2010 +0300
@@ -18,7 +18,7 @@
};
struct master_service_settings_input {
- const struct setting_parser_info **roots;
+ const struct setting_parser_info *const *roots;
const char *config_path;
bool preserve_home;
bool never_exec;
diff -r 8627be1f6de9 -r 46d4f3264417 src/lib-settings/settings-parser.c
--- a/src/lib-settings/settings-parser.c Mon Apr 05 11:04:20 2010 +0300
+++ b/src/lib-settings/settings-parser.c Mon Apr 05 23:06:19 2010 +0300
@@ -259,6 +259,18 @@
return ctx->roots[0].change_struct;
}
+const struct setting_parser_info *const *
+settings_parser_get_roots(const struct setting_parser_context *ctx)
+{
+ const struct setting_parser_info **infos;
+ unsigned int i;
+
+ infos = t_new(const struct setting_parser_info *, ctx->root_count + 1);
+ for (i = 0; i < ctx->root_count; i++)
+ infos[i] = ctx->roots[i].info;
+ return infos;
+}
+
const char *settings_parser_get_error(struct setting_parser_context *ctx)
{
return ctx->error;
@@ -1473,6 +1485,76 @@
} T_END;
}
+static void
+settings_parser_update_children_parent(struct setting_parser_info *parent,
+ pool_t pool)
+{
+ struct setting_define *new_defs;
+ struct setting_parser_info *new_info;
+ unsigned int i, count;
+
+ for (count = 0; parent->defines[count].key != NULL; count++) ;
+
+ new_defs = p_new(pool, struct setting_define, count + 1);
+ memcpy(new_defs, parent->defines, sizeof(*new_defs) * count);
+ parent->defines = new_defs;
+
+ for (i = 0; i < count; i++) {
+ if (new_defs[i].list_info == NULL ||
+ new_defs[i].list_info->parent == NULL)
+ continue;
+
+ new_info = p_new(pool, struct setting_parser_info, 1);
+ *new_info = *new_defs[i].list_info;
+ new_info->parent = parent;
+ new_defs[i].list_info = new_info;
+ }
+}
+
+void settings_parser_dyn_update(pool_t pool,
+ const struct setting_parser_info *const **_roots,
+ const struct dynamic_settings_parser *dyn_parsers)
+{
+ const struct setting_parser_info *const *roots = *_roots;
+ const struct setting_parser_info *old_parent, **new_roots;
+ struct setting_parser_info *new_parent, *new_info;
+ struct dynamic_settings_parser *new_dyn_parsers;
+ unsigned int i, count;
+
+ /* settings_parser_info_update() modifies the parent structure.
+ since we may be using the same structure later, we want it to be
+ in its original state, so we'll have to copy all structures. */
+ old_parent = dyn_parsers[0].info->parent;
+ new_parent = p_new(pool, struct setting_parser_info, 1);
+ *new_parent = *old_parent;
+ settings_parser_update_children_parent(new_parent, pool);
+
+ /* update root */
+ for (count = 0; roots[count] != NULL; count++) ;
+ new_roots = p_new(pool, const struct setting_parser_info *, count + 1);
+ for (i = 0; i < count; i++) {
+ if (roots[i] == old_parent)
+ new_roots[i] = new_parent;
+ else
+ new_roots[i] = roots[i];
+ }
+ *_roots = new_roots;
+
+ /* update parent in dyn_parsers */
+ for (count = 0; dyn_parsers[count].name != NULL; count++) ;
+ new_dyn_parsers = p_new(pool, struct dynamic_settings_parser, count + 1);
+ for (i = 0; i < count; i++) {
+ new_dyn_parsers[i] = dyn_parsers[i];
+
+ new_info = p_new(pool, struct setting_parser_info, 1);
+ *new_info = *dyn_parsers[i].info;
+ new_info->parent = new_parent;
+ new_dyn_parsers[i].info = new_info;
+ }
+
+ settings_parser_info_update(pool, new_parent, new_dyn_parsers);
+}
+
const void *settings_find_dynamic(const struct setting_parser_info *info,
const void *base_set, const char *name)
{
diff -r 8627be1f6de9 -r 46d4f3264417 src/lib-settings/settings-parser.h
--- a/src/lib-settings/settings-parser.h Mon Apr 05 11:04:20 2010 +0300
+++ b/src/lib-settings/settings-parser.h Mon Apr 05 23:06:19 2010 +0300
@@ -114,6 +114,9 @@
void **settings_parser_get_list(const struct setting_parser_context *ctx);
/* Like settings_parser_get(), but return change struct. */
void *settings_parser_get_changes(struct setting_parser_context *ctx);
+/* Returns the setting parser's roots (same as given to init()). */
+const struct setting_parser_info *const *
+settings_parser_get_roots(const struct setting_parser_context *ctx);
/* Return the last error. */
const char *settings_parser_get_error(struct setting_parser_context *ctx);
@@ -194,6 +197,9 @@
void settings_parser_info_update(pool_t pool,
struct setting_parser_info *parent,
const struct dynamic_settings_parser *parsers);
+void settings_parser_dyn_update(pool_t pool,
+ const struct setting_parser_info *const **roots,
+ const struct dynamic_settings_parser *dyn_parsers);
/* Return pointer to beginning of settings for given name, or NULL if there is
no such registered name. */
diff -r 8627be1f6de9 -r 46d4f3264417 src/lib-storage/mail-storage-service.c
--- a/src/lib-storage/mail-storage-service.c Mon Apr 05 11:04:20 2010 +0300
+++ b/src/lib-storage/mail-storage-service.c Mon Apr 05 23:06:19 2010 +0300
@@ -49,7 +49,6 @@
const char *set_cache_module, *set_cache_service;
struct master_service_settings_cache *set_cache;
- const struct setting_parser_info **set_cache_roots;
unsigned int debug:1;
};
@@ -591,77 +590,6 @@
return ctx->conn;
}
-static void
-settings_parser_update_children_parent(struct setting_parser_info *parent,
- pool_t pool)
-{
- struct setting_define *new_defs;
- struct setting_parser_info *new_info;
- unsigned int i, count;
-
- for (count = 0; parent->defines[count].key != NULL; count++) ;
-
- new_defs = p_new(pool, struct setting_define, count + 1);
- memcpy(new_defs, parent->defines, sizeof(*new_defs) * count);
- parent->defines = new_defs;
-
- for (i = 0; i < count; i++) {
- if (new_defs[i].list_info == NULL ||
- new_defs[i].list_info->parent == NULL)
- continue;
-
- new_info = p_new(pool, struct setting_parser_info, 1);
- *new_info = *new_defs[i].list_info;
- new_info->parent = parent;
- new_defs[i].list_info = new_info;
- }
-}
-
-static void
-dyn_parsers_update_parent(pool_t pool,
- const struct setting_parser_info ***_roots,
- const struct dynamic_settings_parser *dyn_parsers)
-{
- const const struct setting_parser_info **roots = *_roots;
- const struct setting_parser_info *old_parent, **new_roots;
- struct setting_parser_info *new_parent, *new_info;
- struct dynamic_settings_parser *new_dyn_parsers;
- unsigned int i, count;
-
- /* settings_parser_info_update() modifies the parent structure.
- since we may be using the same structure later, we want it to be
- in its original state, so we'll have to copy all structures. */
- old_parent = dyn_parsers[0].info->parent;
- new_parent = p_new(pool, struct setting_parser_info, 1);
- *new_parent = *old_parent;
- settings_parser_update_children_parent(new_parent, pool);
-
- /* update root */
- for (count = 0; roots[count] != NULL; count++) ;
- new_roots = p_new(pool, const struct setting_parser_info *, count + 1);
- for (i = 0; i < count; i++) {
- if (roots[i] == old_parent)
- new_roots[i] = new_parent;
- else
- new_roots[i] = roots[i];
- }
- *_roots = new_roots;
-
- /* update parent in dyn_parsers */
- for (count = 0; dyn_parsers[count].name != NULL; count++) ;
- new_dyn_parsers = p_new(pool, struct dynamic_settings_parser, count + 1);
- for (i = 0; i < count; i++) {
- new_dyn_parsers[i] = dyn_parsers[i];
-
- new_info = p_new(pool, struct setting_parser_info, 1);
- *new_info = *dyn_parsers[i].info;
- new_info->parent = new_parent;
- new_dyn_parsers[i].info = new_info;
- }
-
- settings_parser_info_update(pool, new_parent, new_dyn_parsers);
-}
-
int mail_storage_service_read_settings(struct mail_storage_service_ctx *ctx,
const struct mail_storage_service_input *input,
pool_t pool,
@@ -670,6 +598,7 @@
const char **error_r)
{
struct master_service_settings_input set_input;
+ const struct setting_parser_info *const *roots;
struct master_service_settings_output set_output;
const struct dynamic_settings_parser *dyn_parsers;
unsigned int i;
@@ -694,7 +623,6 @@
ctx->set_cache_service = p_strdup(ctx->pool, set_input.service);
ctx->set_cache = master_service_settings_cache_init(
ctx->service, set_input.module, set_input.service);
- ctx->set_cache_roots = ctx->set_roots;
} else {
/* already looked up settings at least once.
we really shouldn't be execing anymore. */
@@ -704,18 +632,15 @@
dyn_parsers = mail_storage_get_dynamic_parsers(pool);
if (null_strcmp(set_input.module, ctx->set_cache_module) == 0 &&
null_strcmp(set_input.service, ctx->set_cache_service) == 0) {
- set_input.roots = ctx->set_cache_roots;
- dyn_parsers_update_parent(ctx->pool, &set_input.roots,
- dyn_parsers);
if (master_service_settings_cache_read(ctx->set_cache,
- &set_input,
+ &set_input, dyn_parsers,
parser_r, error_r) < 0) {
More information about the dovecot-cvs
mailing list