From 635675e89c2fd6ae2a6e9924eb20be086978d91d Mon Sep 17 00:00:00 2001 From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org> Date: Thu, 24 Aug 2017 20:35:12 +0300 Subject: [PATCH] sql: fix memleak in index_opts --- src/box/alter.cc | 2 ++ src/box/index_def.c | 44 +++++++++++++++++++------------------------- src/box/index_def.h | 6 ++++++ 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/box/alter.cc b/src/box/alter.cc index c713226de7..1d65cc9c22 100644 --- a/src/box/alter.cc +++ b/src/box/alter.cc @@ -311,6 +311,8 @@ index_def_new_from_tuple(struct tuple *tuple, struct space *old_space) space_name(old_space), "index name is too long"); } index_opts_create(&opts, tuple_field(tuple, BOX_INDEX_FIELD_OPTS)); + struct index_opts *opts_p = &opts; + auto opts_guard = make_scoped_guard([=] { index_opts_destroy(opts_p); }); const char *parts = tuple_field(tuple, BOX_INDEX_FIELD_PARTS); uint32_t part_count = mp_decode_array(&parts); struct key_def *key_def = key_def_new(part_count); diff --git a/src/box/index_def.c b/src/box/index_def.c index 14956cb00f..806ac121b4 100644 --- a/src/box/index_def.c +++ b/src/box/index_def.c @@ -63,30 +63,6 @@ const struct opt_def index_opts_reg[] = { { NULL, opt_type_MAX, 0, 0 }, }; -/** - * Destructor for struct index_opts. - * The only relevant action so far is to free sql field if not-null. - */ -static void -index_opts_destroy(struct index_opts *opts) -{ - if (opts->sql) { - free(opts->sql); - opts->sql = 0; - } -} - -static void -index_opts_dup(struct index_opts *dst, const struct index_opts *src) -{ - *dst = *src; - if (src->sql) { - dst->sql = (char*)strdup(src->sql); - if (dst->sql == NULL) - diag_set(OutOfMemory, strlen(src->sql), "sql", "char *"); - } -} - struct index_def * index_def_new(uint32_t space_id, uint32_t iid, const char *name, uint32_t name_len, enum index_type type, @@ -124,6 +100,15 @@ index_def_new(uint32_t space_id, uint32_t iid, const char *name, def->space_id = space_id; def->iid = iid; def->opts = *opts; + if (opts->sql != NULL) { + def->opts.sql = strdup(opts->sql); + if (def->opts.sql == NULL) { + diag_set(OutOfMemory, strlen(opts->sql) + 1, "strdup", + "def->opts.sql"); + index_def_delete(def); + return NULL; + } + } return def; } @@ -151,7 +136,16 @@ index_def_dup(const struct index_def *def) return NULL; } rlist_create(&dup->link); - index_opts_dup(&dup->opts, &def->opts); + dup->opts = def->opts; + if (def->opts.sql != NULL) { + dup->opts.sql = strdup(def->opts.sql); + if (dup->opts.sql == NULL) { + diag_set(OutOfMemory, strlen(def->opts.sql) + 1, + "strdup", "dup->opts.sql"); + index_def_delete(dup); + return NULL; + } + } return dup; } diff --git a/src/box/index_def.h b/src/box/index_def.h index ed466aed2f..2ce4d702f9 100644 --- a/src/box/index_def.h +++ b/src/box/index_def.h @@ -102,6 +102,12 @@ struct index_opts { char *sql; }; +static inline void +index_opts_destroy(struct index_opts *opts) +{ + free(opts->sql); +} + extern const struct index_opts index_opts_default; extern const struct opt_def index_opts_reg[]; -- GitLab