From 065c92442276c7720dae2b4b56883c0ca2c4da1c Mon Sep 17 00:00:00 2001 From: Razvan Crainea Date: Mon, 1 Jul 2019 16:57:18 +0300 Subject: [PATCH] acc: fix leak generated by dialog replicated update (cherry picked from commit d8c03f325993e59242f156de01dffa60cc8324b4) --- modules/acc/acc.c | 60 ++++++++++++++++++++++++++++------------- modules/acc/acc_logic.c | 4 +-- modules/acc/acc_logic.h | 1 + 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/modules/acc/acc.c b/modules/acc/acc.c index b76aad3ac38..d9664161971 100644 --- a/modules/acc/acc.c +++ b/modules/acc/acc.c @@ -1591,18 +1591,12 @@ static int prebuild_core_arr(struct dlg_cell *dlg, str *buffer, struct timeval * * * */ -static extra_value_t* restore_extra_from_str(int tags_len, +static int restore_extra_from_str(extra_value_t *values, str* extra_s, int extra_len) { int i; pv_value_t value; - extra_value_t* values; - - if (build_acc_extra_array(tags_len, &values) < 0) { - LM_ERR("failed to build extra pvar list!\n"); - return NULL; - } value.flags = PV_VAL_STR; for (i=0; is += 2 + value.rs.len; extra_s->len -= 2 + value.rs.len; } - return values; + return 0; } static int restore_extra(struct dlg_cell* dlg, @@ -1644,9 +1638,21 @@ static int restore_extra(struct dlg_cell* dlg, buffer.s += 2; buffer.len -= 2; - if ((ctx->extra_values = - restore_extra_from_str(extra_tgs_len, &buffer, extra_len)) == NULL) { + if (extra_len != extra_tgs_len) { + LM_WARN("extra tags were added/removed since last run!" + "won't restore values!\n"); + return 0; + } + + if (!ctx->extra_values && + build_acc_extra_array(extra_len, &ctx->extra_values) < 0) { + LM_ERR("failed to build extra pvar list!\n"); + return -1; + } + + if (restore_extra_from_str(ctx->extra_values, &buffer, extra_len) < 0) { LM_ERR("failed to restore extra values!\n"); + free_extra_array(ctx->extra_values, extra_len); return -1; } @@ -1678,24 +1684,36 @@ static int restore_legs(struct dlg_cell* dlg, return 0; } - ctx->leg_values = shm_malloc(ctx->legs_no * sizeof(leg_value_p)); - if (ctx->leg_values == NULL) { - LM_ERR("no more shm!\n"); - return -1; + if (!ctx->leg_values) { + ctx->leg_values = shm_malloc(ctx->legs_no * sizeof(leg_value_p)); + if (ctx->leg_values == NULL) { + LM_ERR("no more shm!\n"); + return -1; + } + for (i=0; ilegs_no; i++) { + if (build_acc_extra_array(extra_len, &ctx->leg_values[i]) < 0) { + LM_ERR("could not build extra leg %d\n", i); + goto error; + } + } } buffer.s += 4; buffer.len -=4; for (i=0; ilegs_no; i++) { - if ((ctx->leg_values[i] = - restore_extra_from_str(leg_tgs_len, &buffer, extra_len)) == NULL) { + if (restore_extra_from_str(ctx->leg_values[i], &buffer, extra_len) < 0) { LM_ERR("failed to restore leg values!\n"); - return -1; + goto error; } } return 0; +error: + for (i--; i >= 0; i--) + free_extra_array(ctx->leg_values[i], extra_len); + shm_free(ctx->leg_values); + return -1; } int restore_dlg_extra_ctx(struct dlg_cell* dlg, acc_ctx_t *ctx) @@ -1709,6 +1727,8 @@ int restore_dlg_extra_ctx(struct dlg_cell* dlg, acc_ctx_t *ctx) if (leg_tags && restore_legs(dlg, &leg_str, ctx)) { LM_ERR("failed to restore legs!\n"); + if (extra_tgs_len && ctx->extra_values) + free_extra_array(ctx->extra_values, extra_tgs_len); return -1; } return 0; @@ -1736,8 +1756,10 @@ int restore_dlg_extra(struct dlg_cell* dlg, acc_ctx_t** ctx_p) memset(ctx, 0, sizeof(acc_ctx_t)); - if (restore_dlg_extra_ctx(dlg, ctx) < 0) + if (restore_dlg_extra_ctx(dlg, ctx) < 0) { + shm_free(ctx); return -1; + } *ctx_p = ctx; diff --git a/modules/acc/acc_logic.c b/modules/acc/acc_logic.c index 1b9048ffdf4..7e8feab62b7 100644 --- a/modules/acc/acc_logic.c +++ b/modules/acc/acc_logic.c @@ -172,7 +172,7 @@ static void acc_dlg_onwrite(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params); static void acc_cdr_cb( struct cell* t, int type, struct tmcb_params *ps ); -static inline void free_extra_array(extra_value_t* array, int array_len) +void free_extra_array(extra_value_t* array, int array_len) { int i; @@ -1226,8 +1226,6 @@ int init_acc_ctx(acc_ctx_t** ctx_p) LM_ERR("failed to build extra values array!\n"); return -1; } - - if (leg_tags != NULL && push_leg(ctx) < 0) { LM_ERR("failed to build extra values array!\n"); return -1; diff --git a/modules/acc/acc_logic.h b/modules/acc/acc_logic.h index 4919c2af9f0..0202a53c85c 100644 --- a/modules/acc/acc_logic.h +++ b/modules/acc/acc_logic.h @@ -202,5 +202,6 @@ acc_ctx_t* try_fetch_ctx(void); void unref_acc_ctx(void *); void free_global_acc_ctx(acc_ctx_t* ctx); void free_processing_acc_ctx(void* param); +void free_extra_array(extra_value_t* array, int array_len); #endif