From 9dbc175305b607d1002ae9f72e181972b7021b58 Mon Sep 17 00:00:00 2001 From: Matthew Jordan Date: Fri, 18 May 2012 14:01:56 +0000 Subject: [PATCH] Fix a variety of memory leaks This patch addresses a number of memory leaks in a variety of modules that were found by a static analysis tool. A brief summary of the changes: * app_minivm: free ast_str objects on off nominal paths * app_page: free the ast_dial object if the requested channel technology cannot be appended to the dialing structure * app_queue: if a penalty rule failed to match any existing rule list names, the created rule would not be inserted and its memory would be leaked * app_read: dispose of the created silence detector in the presence of off nominal circumstances * app_voicemail: dispose of an allocated unique ID field for MWI event un-subscribe requests in off nominal paths; dispose of configuration objects when using the secret.conf option * chan_dahdi: dispose of the allocated frame produced by ast_dsp_process * chan_iax2: properly unref peer in CLI command "iax2 unregister" * chan_sip: dispose of the allocated frame produced by sip_rtp_read's call of ast_dsp_process; free memory in parse unit tests * func_dialgroup: properly deref ao2 object grhead in nominal path of dialgroup_read * func_odbc: free resultset in off nominal paths of odbc_read * cli: free match_list in off nominal paths of CLI match completion * config: free comment_buffer/list_buffer when configuration file load is unchanged; free the same buffers any time they were created and config files were processed * data: free XML nodes in various places * enum: free context buffer in off nominal paths * features: free ast_call_feature in off nominal paths of applicationmap config processing * netsock2: users of ast_sockaddr_resolve pass in an ast_sockaddr struct that is allocated by the method. Failures in ast_sockaddr_resolve could result in the users of the method not knowing whether or not the buffer was allocated. The method will now not allocate the ast_sockaddr struct if it will return failure. * pbx: cleanup hash table traversals in off nominal paths; free ignore pattern buffer if it already exists for the specified context * xmldoc: cleanup various nodes when we no longer need them * main/editline: various cleanup of pointers not being freed before being assigned to other memory, cleanup along off nominal paths * menuselect/mxml: cleanup of value buffer for an attribute when that attribute did not specify a value * res_calendar*: responses are allocated via the various *_request method returns and should not be allocated in the various write_event methods; ensure attendee buffer is freed if no data exists in the parsed node; ensure that calendar objects are de-ref'd appropriately * res_jabber: free buffer in off nominal path * res_musiconhold: close the DIR* object in off nominal paths * res_rtp_asterisk: if we run out of ports, close the rtp socket object and free the rtp object * res_srtp: if we fail to create the session in libsrtp, destroy the temporary ast_srtp object (issue ASTERISK-19665) Reported by: Matt Jordan Review: https://reviewboard.asterisk.org/r/1922 ........ Merged revisions 366880 from http://svn.asterisk.org/svn/asterisk/branches/1.8 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/10@366881 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- apps/app_minivm.c | 6 +++++ apps/app_page.c | 1 + apps/app_queue.c | 9 +++++++ apps/app_record.c | 8 +++--- apps/app_voicemail.c | 47 ++++++++++++++++++++++++------------ channels/chan_dahdi.c | 5 +++- channels/chan_iax2.c | 2 ++ channels/chan_sip.c | 2 ++ channels/sip/config_parser.c | 6 ++++- funcs/func_dialgroup.c | 1 + funcs/func_odbc.c | 3 +++ main/cli.c | 6 +++-- main/config.c | 6 +++-- main/data.c | 2 ++ main/editline/readline.c | 8 +++++- main/editline/term.c | 16 +++++++++--- main/editline/tokenizer.c | 9 +++++-- main/enum.c | 3 +++ main/features.c | 2 ++ main/netsock2.c | 4 +++ main/pbx.c | 3 +++ main/xmldoc.c | 4 +++ res/res_calendar.c | 14 +++++++++-- res/res_calendar_caldav.c | 13 +++++----- res/res_calendar_exchange.c | 5 ++-- res/res_calendar_icalendar.c | 8 +++--- res/res_jabber.c | 1 + res/res_musiconhold.c | 2 ++ res/res_rtp_asterisk.c | 2 ++ res/res_srtp.c | 4 ++- 30 files changed, 156 insertions(+), 46 deletions(-) diff --git a/apps/app_minivm.c b/apps/app_minivm.c index edffd4d3f4..b88653d3f8 100644 --- a/apps/app_minivm.c +++ b/apps/app_minivm.c @@ -1255,6 +1255,8 @@ static int sendmail(struct minivm_template *template, struct minivm_account *vmu if (ast_strlen_zero(email)) { ast_log(LOG_WARNING, "No address to send message to.\n"); + ast_free(str1); + ast_free(str2); return -1; } @@ -1309,11 +1311,15 @@ static int sendmail(struct minivm_template *template, struct minivm_account *vmu } if (!p) { ast_log(LOG_WARNING, "Unable to open temporary file '%s'\n", tmp); + ast_free(str1); + ast_free(str2); return -1; } /* Allocate channel used for chanvar substitution */ ast = ast_dummy_channel_alloc(); if (!ast) { + ast_free(str1); + ast_free(str2); return -1; } diff --git a/apps/app_page.c b/apps/app_page.c index 9908bcbcd2..2a8f85a7b7 100644 --- a/apps/app_page.c +++ b/apps/app_page.c @@ -248,6 +248,7 @@ static int page_exec(struct ast_channel *chan, const char *data) /* Append technology and resource */ if (ast_dial_append(dial, tech, resource) == -1) { ast_log(LOG_ERROR, "Failed to add %s to outbound dial\n", tech); + ast_dial_destroy(dial); continue; } diff --git a/apps/app_queue.c b/apps/app_queue.c index 535170205d..cba347f12a 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -1851,9 +1851,17 @@ static int insert_penaltychange(const char *list_name, const char *content, cons if (!inserted) { AST_LIST_INSERT_TAIL(&rl_iter->rules, rule, list); + inserted = 1; } + + break; } + if (!inserted) { + ast_log(LOG_WARNING, "Unknown rule list name %s; ignoring.\n", list_name); + ast_free(rule); + return -1; + } return 0; } @@ -4319,6 +4327,7 @@ static struct ast_datastore *setup_transfer_datastore(struct queue_ent *qe, stru ast_channel_lock(qe->chan); if (!(ds = ast_datastore_alloc(&queue_transfer_info, NULL))) { ast_channel_unlock(qe->chan); + ast_free(qtds); ast_log(LOG_WARNING, "Unable to create transfer datastore. queue_log will not show attended transfer\n"); return NULL; } diff --git a/apps/app_record.c b/apps/app_record.c index 6098ca7290..91fbd984b4 100644 --- a/apps/app_record.c +++ b/apps/app_record.c @@ -415,12 +415,14 @@ static int record_exec(struct ast_channel *chan, const char *data) out: if ((silence > 0) && rfmt.id) { res = ast_set_read_format(chan, &rfmt); - if (res) + if (res) { ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name); - if (sildet) - ast_dsp_free(sildet); + } } + if (sildet) { + ast_dsp_free(sildet); + } return res; } diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c index 58f96fd865..7101cb5c96 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c @@ -11517,16 +11517,22 @@ static int handle_subscribe(void *datap) static void mwi_unsub_event_cb(const struct ast_event *event, void *userdata) { uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid)); - if (ast_event_get_type(event) != AST_EVENT_UNSUB) + + if (!uniqueid) { + ast_log(LOG_ERROR, "Unable to allocate memory for uniqueid\n"); return; + } - if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI) + if (ast_event_get_type(event) != AST_EVENT_UNSUB) { + ast_free(uniqueid); return; + } - if (!uniqueid) { - ast_log(LOG_ERROR, "Unable to allocate memory for uniqueid\n"); + if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI) { + ast_free(uniqueid); return; } + u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID); *uniqueid = u; if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) { @@ -12510,8 +12516,10 @@ static void read_password_from_file(const char *secretfn, char *password, int pa const char *val = ast_variable_retrieve(pwconf, "general", "password"); if (val) { ast_copy_string(password, val, passwordlen); - return; + ast_config_destroy(pwconf); + return; } + ast_config_destroy(pwconf); } ast_log(LOG_NOTICE, "Failed reading voicemail password from %s, using secret from config file\n", secretfn); } @@ -12520,26 +12528,33 @@ static int write_password_to_file(const char *secretfn, const char *password) { struct ast_config *conf; struct ast_category *cat; struct ast_variable *var; + int res = -1; - if (!(conf=ast_config_new())) { + if (!(conf = ast_config_new())) { ast_log(LOG_ERROR, "Error creating new config structure\n"); - return -1; + return res; } - if (!(cat=ast_category_new("general","",1))) { + if (!(cat = ast_category_new("general", "", 1))) { ast_log(LOG_ERROR, "Error creating new category structure\n"); - return -1; + ast_config_destroy(conf); + return res; } - if (!(var=ast_variable_new("password",password,""))) { + if (!(var = ast_variable_new("password", password, ""))) { ast_log(LOG_ERROR, "Error creating new variable structure\n"); - return -1; + ast_config_destroy(conf); + ast_category_destroy(cat); + return res; } - ast_category_append(conf,cat); - ast_variable_append(cat,var); - if (ast_config_text_file_save(secretfn, conf, "app_voicemail")) { + ast_category_append(conf, cat); + ast_variable_append(cat, var); + if (!ast_config_text_file_save(secretfn, conf, "app_voicemail")) { + res = 0; + } else { ast_log(LOG_ERROR, "Error writing voicemail password to %s\n", secretfn); - return -1; } - return 0; + + ast_config_destroy(conf); + return res; } static int vmsayname_exec(struct ast_channel *chan, const char *data) diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 85b621882a..ebd1ea5ede 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -9304,6 +9304,7 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast) if ((ast->_state == AST_STATE_UP) && !p->outgoing) { /* Treat this as a "hangup" instead of a "busy" on the assumption that a busy */ + ast_frfree(f); f = NULL; } } else if (f->frametype == AST_FRAME_DTMF_BEGIN @@ -9329,7 +9330,8 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast) if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) { p->waitingfordt.tv_sec = 0; ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel); - f=NULL; + ast_frfree(f); + f = NULL; } else if (f->frametype == AST_FRAME_VOICE) { f->frametype = AST_FRAME_NULL; f->subclass.integer = 0; @@ -9344,6 +9346,7 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast) ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel); p->dop.dialstr[0] = '\0'; ast_mutex_unlock(&p->lock); + ast_frfree(f); return NULL; } else { ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index a92f04f4a0..a9c58a80aa 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -6990,6 +6990,7 @@ static char *handle_cli_iax2_unregister(struct ast_cli_entry *e, int cmd, struct } else { ast_cli(a->fd, "Peer %s not registered\n", a->argv[2]); } + peer_unref(p); } else { ast_cli(a->fd, "Peer unknown: %s. Not unregistered\n", a->argv[2]); } @@ -9942,6 +9943,7 @@ static int acf_iaxvar_write(struct ast_channel *chan, const char *cmd, char *dat } varlist = ast_calloc(1, sizeof(*varlist)); if (!varlist) { + ast_datastore_free(variablestore); ast_log(LOG_ERROR, "Unable to assign new variable '%s'\n", data); return -1; } diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 494f45df8a..60fd68f26d 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -7573,6 +7573,7 @@ static struct ast_frame *sip_read(struct ast_channel *ast) if (ast_async_goto(ast, target_context, "fax", 1)) { ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); } + ast_frfree(fr); fr = &ast_null_frame; } else { ast_channel_lock(ast); @@ -7584,6 +7585,7 @@ static struct ast_frame *sip_read(struct ast_channel *ast) /* Only allow audio through if they sent progress with SDP, or if the channel is actually answered */ if (fr && fr->frametype == AST_FRAME_VOICE && p->invitestate != INV_EARLY_MEDIA && ast->_state != AST_STATE_UP) { + ast_frfree(fr); fr = &ast_null_frame; } diff --git a/channels/sip/config_parser.c b/channels/sip/config_parser.c index 89f1a988ed..239346bf4d 100644 --- a/channels/sip/config_parser.c +++ b/channels/sip/config_parser.c @@ -556,6 +556,8 @@ AST_TEST_DEFINE(sip_parse_register_line_test) ast_test_status_update(test, "Test 12, add domain port failed.\n"); res = AST_TEST_FAIL; } + ast_string_field_free_memory(reg); + ast_free(reg); /* ---Test reg13, domain port without secret --- */ if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) { @@ -582,7 +584,9 @@ AST_TEST_DEFINE(sip_parse_register_line_test) ast_test_status_update(test, "Test 13, domain port without secret failed.\n"); res = AST_TEST_FAIL; -} + } + ast_string_field_free_memory(reg); + ast_free(reg); /* ---Test reg 9, missing domain, expected to fail --- */ if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) { diff --git a/funcs/func_dialgroup.c b/funcs/func_dialgroup.c index c3322e3f9b..0e078cd80d 100644 --- a/funcs/func_dialgroup.c +++ b/funcs/func_dialgroup.c @@ -165,6 +165,7 @@ static int dialgroup_read(struct ast_channel *chan, const char *cmd, char *data, ao2_ref(entry, -1); } ao2_iterator_destroy(&i); + ao2_ref(grhead, -1); return res; } diff --git a/funcs/func_odbc.c b/funcs/func_odbc.c index edb69f0930..667e093b30 100644 --- a/funcs/func_odbc.c +++ b/funcs/func_odbc.c @@ -539,6 +539,7 @@ static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, cha pbx_builtin_setvar_helper(chan, "ODBCROWS", rowcount); ast_autoservice_stop(chan); } + ast_free(resultset); return -1; } @@ -553,6 +554,7 @@ static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, cha pbx_builtin_setvar_helper(chan, "ODBCROWS", rowcount); ast_autoservice_stop(chan); } + ast_free(resultset); return -1; } @@ -578,6 +580,7 @@ static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, cha pbx_builtin_setvar_helper(chan, "ODBCSTATUS", status); ast_autoservice_stop(chan); } + ast_free(resultset); return res1; } diff --git a/main/cli.c b/main/cli.c index c35b941d10..5802c1d54c 100644 --- a/main/cli.c +++ b/main/cli.c @@ -2340,9 +2340,11 @@ char **ast_cli_completion_matches(const char *text, const char *word) max_equal = i; } - if (!(retstr = ast_malloc(max_equal + 1))) + if (!(retstr = ast_malloc(max_equal + 1))) { + ast_free(match_list); return NULL; - + } + ast_copy_string(retstr, match_list[1], max_equal + 1); match_list[0] = retstr; diff --git a/main/config.c b/main/config.c index 668fba1bd9..ac8063e09e 100644 --- a/main/config.c +++ b/main/config.c @@ -1487,6 +1487,8 @@ static struct ast_config *config_text_file_load(const char *database, const char if (unchanged) { AST_LIST_UNLOCK(&cfmtime_head); + ast_free(comment_buffer); + ast_free(lline_buffer); return CONFIG_STATUS_FILEUNCHANGED; } } @@ -1641,13 +1643,13 @@ static struct ast_config *config_text_file_load(const char *database, const char } #endif - if (cfg && cfg != CONFIG_STATUS_FILEUNCHANGED && cfg != CONFIG_STATUS_FILEINVALID && cfg->include_level == 1 && ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS)) { + if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS)) { ast_free(comment_buffer); ast_free(lline_buffer); comment_buffer = NULL; lline_buffer = NULL; } - + if (count == 0) return NULL; diff --git a/main/data.c b/main/data.c index a9ccb73a22..47e7fd5bda 100644 --- a/main/data.c +++ b/main/data.c @@ -1042,6 +1042,7 @@ static int data_search_cmp_ptr(const struct ast_data_search *root, const char *n cmp_type = child->cmp_type; if (sscanf(child->value, "%p", &node_ptr) <= 0) { + ao2_ref(child, -1); return 1; } @@ -2186,6 +2187,7 @@ struct ast_xml_doc *ast_data_get_xml(const struct ast_data_query *query) doc = ast_xml_new(); if (!doc) { + ast_data_free(res); return NULL; } diff --git a/main/editline/readline.c b/main/editline/readline.c index 4729fa952f..77827c3f91 100644 --- a/main/editline/readline.c +++ b/main/editline/readline.c @@ -549,6 +549,7 @@ _history_expand_command(const char *command, size_t cmdlen, char **result) from = strdup(search); else { from = NULL; + free(line); return (-1); } } @@ -609,8 +610,13 @@ _history_expand_command(const char *command, size_t cmdlen, char **result) end = max - ((end < -1) ? 1 : 0); /* check boundaries ... */ - if (start > max || end > max || start > end) + if (start > max || end > max || start > end) { + for (i = 0; i <= max; i++) { + free(arr[i]); + } + free(arr), arr = (char **) NULL; return (-1); + } for (i = 0; i <= max; i++) { char *temp; diff --git a/main/editline/term.c b/main/editline/term.c index fb627cabb7..63cec6e43e 100644 --- a/main/editline/term.c +++ b/main/editline/term.c @@ -472,7 +472,7 @@ term_rebuffer_display(EditLine *el) private int term_alloc_display(EditLine *el) { - int i; + int i, j; char **b; coord_t *c = &el->el_term.t_size; @@ -481,8 +481,13 @@ term_alloc_display(EditLine *el) return (-1); for (i = 0; i < c->v; i++) { b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1))); - if (b[i] == NULL) + if (b[i] == NULL) { + for (j = 0; j < i; j++) { + el_free(b[j]); + } + el_free(b); return (-1); + } } b[c->v] = NULL; el->el_display = b; @@ -492,8 +497,13 @@ term_alloc_display(EditLine *el) return (-1); for (i = 0; i < c->v; i++) { b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1))); - if (b[i] == NULL) + if (b[i] == NULL) { + for (j = 0; j < i; j++) { + el_free(b[j]); + } + el_free(b); return (-1); + } } b[c->v] = NULL; el->el_vdisplay = b; diff --git a/main/editline/tokenizer.c b/main/editline/tokenizer.c index f0de39bc9f..67398c6869 100644 --- a/main/editline/tokenizer.c +++ b/main/editline/tokenizer.c @@ -113,12 +113,17 @@ tok_init(const char *ifs) tok->argc = 0; tok->amax = AINCR; tok->argv = (char **) tok_malloc(sizeof(char *) * tok->amax); - if (tok->argv == NULL) + if (tok->argv == NULL) { + tok_free(tok); return (NULL); + } tok->argv[0] = NULL; tok->wspace = (char *) tok_malloc(WINCR); - if (tok->wspace == NULL) + if (tok->wspace == NULL) { + tok_free(tok->argv); + tok_free(tok); return (NULL); + } tok->wmax = tok->wspace + WINCR; tok->wstart = tok->wspace; tok->wptr = tok->wspace; diff --git a/main/enum.c b/main/enum.c index 92f185c607..d590666519 100644 --- a/main/enum.c +++ b/main/enum.c @@ -790,6 +790,7 @@ int ast_get_enum(struct ast_channel *chan, const char *number, char *dst, int ds if (sdl > strlen(number)) { /* Number too short for this sdl? */ ast_log(LOG_WARNING, "I-ENUM: subdomain location %d behind number %s\n", sdl, number); + ast_free(context); return 0; } ast_copy_string(left, number + sdl, sizeof(left)); @@ -802,6 +803,7 @@ int ast_get_enum(struct ast_channel *chan, const char *number, char *dst, int ds /* check the space we need for middle */ if ((sdl * 2 + strlen(middle) + 2) > sizeof(middle)) { ast_log(LOG_WARNING, "ast_get_enum: not enough space for I-ENUM rewrite.\n"); + ast_free(context); return -1; } @@ -819,6 +821,7 @@ int ast_get_enum(struct ast_channel *chan, const char *number, char *dst, int ds if (strlen(left) * 2 + 2 > sizeof(domain)) { ast_log(LOG_WARNING, "string to long in ast_get_enum\n"); + ast_free(context); return -1; } diff --git a/main/features.c b/main/features.c index 7c47c85f56..aa62b5b3af 100644 --- a/main/features.c +++ b/main/features.c @@ -5740,6 +5740,7 @@ static void process_applicationmap_line(struct ast_variable *var) } else { ast_log(LOG_NOTICE, "Invalid 'ActivateOn' specification for feature '%s'," " must be 'self', or 'peer'\n", var->name); + ast_free(feature); return; } @@ -5754,6 +5755,7 @@ static void process_applicationmap_line(struct ast_variable *var) } else { ast_log(LOG_NOTICE, "Invalid 'ActivatedBy' specification for feature '%s'," " must be 'caller', or 'callee', or 'both'\n", var->name); + ast_free(feature); return; } diff --git a/main/netsock2.c b/main/netsock2.c index 1922ac3881..5ae4ceb709 100644 --- a/main/netsock2.c +++ b/main/netsock2.c @@ -270,6 +270,10 @@ int ast_sockaddr_resolve(struct ast_sockaddr **addrs, const char *str, res_cnt++; } + if (res_cnt == 0) { + goto cleanup; + } + if ((*addrs = ast_malloc(res_cnt * sizeof(struct ast_sockaddr))) == NULL) { res_cnt = 0; goto cleanup; diff --git a/main/pbx.c b/main/pbx.c index d0a24df9cb..8da4bb0161 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -7493,6 +7493,8 @@ static void context_merge(struct ast_context **extcontexts, struct ast_hashtab * if (!new) { ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name); + ast_hashtab_end_traversal(prio_iter); + ast_hashtab_end_traversal(exten_iter); return; /* no sense continuing. */ } /* we will not replace existing entries in the new context with stuff from the old context. @@ -8218,6 +8220,7 @@ int ast_context_add_ignorepat2(struct ast_context *con, const char *value, const if (!strcasecmp(ignorepatc->pattern, value)) { /* Already there */ ast_unlock_context(con); + ast_free(ignorepat); errno = EEXIST; return -1; } diff --git a/main/xmldoc.c b/main/xmldoc.c index 1c5fe3d1ba..b940404c92 100644 --- a/main/xmldoc.c +++ b/main/xmldoc.c @@ -1666,6 +1666,7 @@ static void xmldoc_parse_optionlist(struct ast_xml_node *fixnode, const char *ta ast_str_append(buffer, 0, "\n"); ast_xml_free_attr(optname); ast_xml_free_attr(hasparams); + ast_free(optionsyntax); } } @@ -1740,12 +1741,14 @@ char *ast_xmldoc_build_arguments(const char *type, const char *name, const char char *retstr = NULL; if (ast_strlen_zero(type) || ast_strlen_zero(name)) { + ast_free(ret); return NULL; } node = xmldoc_get_node(type, name, module, documentation_language); if (!node || !ast_xml_node_get_children(node)) { + ast_free(ret); return NULL; } @@ -1758,6 +1761,7 @@ char *ast_xmldoc_build_arguments(const char *type, const char *name, const char if (!node || !ast_xml_node_get_children(node)) { /* We couldn't find the syntax node. */ + ast_free(ret); return NULL; } diff --git a/res/res_calendar.c b/res/res_calendar.c index bd06fe82de..18d778ce4f 100644 --- a/res/res_calendar.c +++ b/res/res_calendar.c @@ -362,6 +362,7 @@ static int calendar_is_busy(struct ast_calendar *cal) static enum ast_device_state calendarstate(const char *data) { + enum ast_device_state state; struct ast_calendar *cal; if (ast_strlen_zero(data) || (!(cal = find_calendar(data)))) { @@ -369,10 +370,13 @@ static enum ast_device_state calendarstate(const char *data) } if (cal->tech->is_busy) { - return cal->tech->is_busy(cal) ? AST_DEVICE_INUSE : AST_DEVICE_NOT_INUSE; + state = cal->tech->is_busy(cal) ? AST_DEVICE_INUSE : AST_DEVICE_NOT_INUSE; + } else { + state = calendar_is_busy(cal) ? AST_DEVICE_INUSE : AST_DEVICE_NOT_INUSE; } - return calendar_is_busy(cal) ? AST_DEVICE_INUSE : AST_DEVICE_NOT_INUSE; + cal = unref_calendar(cal); + return state; } static struct ast_calendar *build_calendar(struct ast_config *cfg, const char *cat, const struct ast_calendar_tech *tech) @@ -1048,6 +1052,7 @@ static int calendar_busy_exec(struct ast_channel *chan, const char *cmd, char *d } strcpy(buf, calendar_is_busy(cal) ? "1" : "0"); + cal = unref_calendar(cal); return 0; } @@ -1202,6 +1207,8 @@ static int calendar_query_exec(struct ast_channel *chan, const char *cmd, char * ast_debug(10, "%s (%ld - %ld) overlapped with (%ld - %ld)\n", event->summary, (long) event->start, (long) event->end, (long) start, (long) end); if (add_event_to_list(events, event, start, end) < 0) { event = ast_calendar_unref_event(event); + cal = unref_calendar(cal); + ao2_ref(events, -1); ao2_iterator_destroy(&i); return -1; } @@ -1219,6 +1226,8 @@ static int calendar_query_exec(struct ast_channel *chan, const char *cmd, char * if (!(eventlist_datastore = ast_datastore_alloc(&eventlist_datastore_info, buf))) { ast_log(LOG_ERROR, "Could not allocate datastore!\n"); + cal = unref_calendar(cal); + ao2_ref(events, -1); return -1; } @@ -1229,6 +1238,7 @@ static int calendar_query_exec(struct ast_channel *chan, const char *cmd, char * ast_channel_datastore_add(chan, eventlist_datastore); ast_channel_unlock(chan); + cal = unref_calendar(cal); return 0; } diff --git a/res/res_calendar_caldav.c b/res/res_calendar_caldav.c index f569b9eab3..21c180f227 100644 --- a/res/res_calendar_caldav.c +++ b/res/res_calendar_caldav.c @@ -181,9 +181,8 @@ static int caldav_write_event(struct ast_calendar_event *event) return -1; } if (!(body = ast_str_create(512)) || - !(subdir = ast_str_create(32)) || - !(response = ast_str_create(512))) { - ast_log(LOG_ERROR, "Could not allocate memory for request and response!\n"); + !(subdir = ast_str_create(32))) { + ast_log(LOG_ERROR, "Could not allocate memory for request!\n"); goto write_cleanup; } @@ -406,10 +405,12 @@ static void caldav_add_event(icalcomponent *comp, struct icaltime_span *span, vo return; } data = icalproperty_get_attendee(prop); - if (!ast_strlen_zero(data)) { - attendee->data = ast_strdup(data);; - AST_LIST_INSERT_TAIL(&event->attendees, attendee, next); + if (ast_strlen_zero(data)) { + ast_free(attendee); + continue; } + attendee->data = ast_strdup(data); + AST_LIST_INSERT_TAIL(&event->attendees, attendee, next); } diff --git a/res/res_calendar_exchange.c b/res/res_calendar_exchange.c index 4a2df1822c..968686293b 100644 --- a/res/res_calendar_exchange.c +++ b/res/res_calendar_exchange.c @@ -433,9 +433,8 @@ static int exchangecal_write_event(struct ast_calendar_event *event) return -1; } if (!(body = ast_str_create(512)) || - !(subdir = ast_str_create(32)) || - !(response = ast_str_create(512))) { - ast_log(LOG_ERROR, "Could not allocate memory for request and response!\n"); + !(subdir = ast_str_create(32))) { + ast_log(LOG_ERROR, "Could not allocate memory for request!\n"); goto write_cleanup; } diff --git a/res/res_calendar_icalendar.c b/res/res_calendar_icalendar.c index b177b49411..dc7b5f31cd 100644 --- a/res/res_calendar_icalendar.c +++ b/res/res_calendar_icalendar.c @@ -261,10 +261,12 @@ static void icalendar_add_event(icalcomponent *comp, struct icaltime_span *span, return; } data = icalproperty_get_attendee(prop); - if (!ast_strlen_zero(data)) { - attendee->data = ast_strdup(data);; - AST_LIST_INSERT_TAIL(&event->attendees, attendee, next); + if (ast_strlen_zero(data)) { + ast_free(attendee); + continue; } + attendee->data = ast_strdup(data);; + AST_LIST_INSERT_TAIL(&event->attendees, attendee, next); } diff --git a/res/res_jabber.c b/res/res_jabber.c index 870508d032..cd657e759e 100644 --- a/res/res_jabber.c +++ b/res/res_jabber.c @@ -2294,6 +2294,7 @@ static void aji_handle_message(struct aji_client *client, ikspak *pak) /* insert will furtherly be added to message list */ insert->from = ast_strdup(pak->from->full); if (!insert->from) { + ast_free(insert); ast_log(LOG_ERROR, "Memory allocation failure\n"); return; } diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c index 34124e9ba1..9b5cb8c5c5 100644 --- a/res/res_musiconhold.c +++ b/res/res_musiconhold.c @@ -1092,10 +1092,12 @@ static int moh_scan_files(struct mohclass *class) { class->total_files = 0; if (!getcwd(path, sizeof(path))) { ast_log(LOG_WARNING, "getcwd() failed: %s\n", strerror(errno)); + closedir(files_DIR); return -1; } if (chdir(dir_path) < 0) { ast_log(LOG_WARNING, "chdir() failed: %s\n", strerror(errno)); + closedir(files_DIR); return -1; } while ((files_dirent = readdir(files_DIR))) { diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c index 27329c6dff..b5819b0f24 100644 --- a/res/res_rtp_asterisk.c +++ b/res/res_rtp_asterisk.c @@ -566,6 +566,8 @@ static int ast_rtp_new(struct ast_rtp_instance *instance, /* See if we ran out of ports or if the bind actually failed because of something other than the address being in use */ if (x == startplace || errno != EADDRINUSE) { ast_log(LOG_ERROR, "Oh dear... we couldn't allocate a port for RTP instance '%p'\n", instance); + close(rtp->s); + ast_free(rtp); return -1; } } diff --git a/res/res_srtp.c b/res/res_srtp.c index 756c62e2fa..f651c40675 100644 --- a/res/res_srtp.c +++ b/res/res_srtp.c @@ -433,12 +433,14 @@ static int ast_srtp_create(struct ast_srtp **srtp, struct ast_rtp_instance *rtp, if (!(temp = res_srtp_new())) { return -1; } + ast_module_ref(ast_module_info->self); + /* Any failures after this point can use ast_srtp_destroy to destroy the instance */ if (srtp_create(&temp->session, &policy->sp) != err_status_ok) { + ast_srtp_destroy(temp); return -1; } - ast_module_ref(ast_module_info->self); temp->rtp = rtp; *srtp = temp;