summaryrefslogtreecommitdiff
path: root/main/pbx.c
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2014-11-12 16:12:32 +0000
committerJoshua Colp <jcolp@digium.com>2014-11-12 16:12:32 +0000
commit5ee03e74a845fa022939bf029323420cb8180fd8 (patch)
treecf6d682a4f21dd9bb1190086bd5ab23b890e5efe /main/pbx.c
parent5ca2b16721139a7ec27fd658a72f657fa232b588 (diff)
pbx: Fix off-nominal case where a freed extension may still be used.
If during the operation of adding an extension a priority is added but fails it is possible for the extension to be freed but still exist in the PBX core. If this occurs subsequent lookups may try to access the extension and end up in freed memory. This change removes the extension from the PBX core when the priority addition fails and then frees the extension. ASTERISK-24444 #close Reported by: Leandro Dardini Review: https://reviewboard.asterisk.org/r/4162/ ........ Merged revisions 427709 from http://svn.asterisk.org/svn/asterisk/branches/11 ........ Merged revisions 427710 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/13@427711 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/pbx.c')
-rw-r--r--main/pbx.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/main/pbx.c b/main/pbx.c
index d814c5ac6..b605a9143 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -9791,13 +9791,7 @@ static int add_priority(struct ast_context *con, struct ast_exten *tmp,
"Unable to register extension '%s' priority %d in '%s', already in use\n",
tmp->exten, tmp->priority, con->name);
}
- if (tmp->datad) {
- tmp->datad(tmp->data);
- /* if you free this, null it out */
- tmp->data = NULL;
- }
- ast_free(tmp);
return -1;
}
/* we are replacing e, so copy the link fields and then update
@@ -10081,6 +10075,26 @@ static int ast_add_extension2_lockopt(struct ast_context *con,
}
if (e && res == 0) { /* exact match, insert in the priority chain */
res = add_priority(con, tmp, el, e, replace);
+ if (res < 0) {
+ if (con->pattern_tree) {
+ struct match_char *x = add_exten_to_pattern_tree(con, tmp, 1);
+
+ if (x->exten) {
+ x->deleted = 1;
+ x->exten = 0;
+ }
+
+ ast_hashtab_remove_this_object(con->root_table, tmp);
+ }
+
+ if (tmp->datad) {
+ tmp->datad(tmp->data);
+ /* if you free this, null it out */
+ tmp->data = NULL;
+ }
+
+ ast_free(tmp);
+ }
if (lock_context) {
ast_unlock_context(con);
}