[Asterisk-code-review] app page.c: Fix crash when forwarding with a predial handler. (asterisk[certified/13.1])

Joshua Colp asteriskteam at digium.com
Wed Sep 23 11:45:54 CDT 2015


Joshua Colp has submitted this change and it was merged.

Change subject: app_page.c: Fix crash when forwarding with a predial handler.
......................................................................


app_page.c: Fix crash when forwarding with a predial handler.

Page uses the async method of dialing with the dial API.  When a call gets
forwarded there is no calling channel available.  If the predial handler
was set then the calling channel could not be put into auto-service
for the forwarded call because it doesn't exist.  A crash is the result.

* Moved the callee predial parameter string processing to before the
string is passed to the dial API rather than having the dial API do it.
There are a few benefits do doing this.  The first is the predial
parameter string processing doesn't need to be done for each channel
called by the dial API.  The second is in async mode and the forwarded
channel is to have the predial handler executed on it then the
non-existent calling channel does not need to be present to process the
predial parameter string.

* Don't start auto-service on a non-existent calling channel to execute
the predial handler when the dial API is in async mode and forwarding a
call.

ASTERISK-25384 #close
Reported by: Chet Stevens

Change-Id: If53892b286d29f6cf955e2545b03dcffa2610981
---
M apps/app_page.c
M main/dial.c
2 files changed, 28 insertions(+), 25 deletions(-)

Approvals:
  Kevin Harwell: Looks good to me, but someone else must approve
  Anonymous Coward #1000019: Verified
  Joshua Colp: Looks good to me, approved



diff --git a/apps/app_page.c b/apps/app_page.c
index f5e1460..cd87e06 100644
--- a/apps/app_page.c
+++ b/apps/app_page.c
@@ -249,12 +249,18 @@
 
 static int page_exec(struct ast_channel *chan, const char *data)
 {
-	char *tech, *resource, *tmp;
-	char confbridgeopts[128], originator[AST_CHANNEL_NAME];
+	char *tech;
+	char *resource;
+	char *tmp;
+	char *predial_callee = NULL;
+	char confbridgeopts[128];
+	char originator[AST_CHANNEL_NAME];
 	struct page_options options = { { 0, }, { 0, } };
 	unsigned int confid = ast_random();
 	struct ast_app *app;
-	int res = 0, pos = 0, i = 0;
+	int res = 0;
+	int pos = 0;
+	int i = 0;
 	struct ast_dial **dial_list;
 	unsigned int num_dials;
 	int timeout = 0;
@@ -310,6 +316,15 @@
 		return -1;
 	}
 
+	/* PREDIAL: Preprocess any callee gosub arguments. */
+	if (ast_test_flag(&options.flags, PAGE_PREDIAL_CALLEE)
+		&& !ast_strlen_zero(options.opts[OPT_ARG_PREDIAL_CALLEE])) {
+		ast_replace_subargument_delimiter(options.opts[OPT_ARG_PREDIAL_CALLEE]);
+		predial_callee =
+			(char *) ast_app_expand_sub_args(chan, options.opts[OPT_ARG_PREDIAL_CALLEE]);
+	}
+
+	/* PREDIAL: Run gosub on the caller's channel */
 	if (ast_test_flag(&options.flags, PAGE_PREDIAL_CALLER)
 		&& !ast_strlen_zero(options.opts[OPT_ARG_PREDIAL_CALLER])) {
 		ast_replace_subargument_delimiter(options.opts[OPT_ARG_PREDIAL_CALLER]);
@@ -360,9 +375,8 @@
 		/* Set ANSWER_EXEC as global option */
 		ast_dial_option_global_enable(dial, AST_DIAL_OPTION_ANSWER_EXEC, confbridgeopts);
 
-		if (ast_test_flag(&options.flags, PAGE_PREDIAL_CALLEE)
-			&& !ast_strlen_zero(options.opts[OPT_ARG_PREDIAL_CALLEE])) {
-			ast_dial_option_global_enable(dial, AST_DIAL_OPTION_PREDIAL, options.opts[OPT_ARG_PREDIAL_CALLEE]);
+		if (predial_callee) {
+			ast_dial_option_global_enable(dial, AST_DIAL_OPTION_PREDIAL, predial_callee);
 		}
 
 		if (timeout) {
@@ -383,6 +397,8 @@
 		dial_list[pos++] = dial;
 	}
 
+	ast_free(predial_callee);
+
 	if (!ast_test_flag(&options.flags, PAGE_QUIET)) {
 		res = ast_streamfile(chan, "beep", ast_channel_language(chan));
 		if (!res)
diff --git a/main/dial.c b/main/dial.c
index 4d5ef34..c8c1a78 100644
--- a/main/dial.c
+++ b/main/dial.c
@@ -377,14 +377,13 @@
 	ast_channel_unlock(channel->owner);
 
 	if (!ast_strlen_zero(predial_string)) {
-		const char *predial_callee = ast_app_expand_sub_args(chan, predial_string);
-		if (!predial_callee) {
-			ast_log(LOG_ERROR, "Could not expand subroutine arguments in predial request '%s'\n", predial_string);
+		if (chan) {
+			ast_autoservice_start(chan);
 		}
-		ast_autoservice_start(chan);
-		ast_pre_call(channel->owner, predial_callee);
-		ast_autoservice_stop(chan);
-		ast_free((char *) predial_callee);
+		ast_pre_call(channel->owner, predial_string);
+		if (chan) {
+			ast_autoservice_stop(chan);
+		}
 	}
 
 	return 0;
@@ -395,10 +394,6 @@
 	struct ast_dial_channel *channel;
 	int res = -1;
 	char *predial_string = dial->options[AST_DIAL_OPTION_PREDIAL];
-
-	if (!ast_strlen_zero(predial_string)) {
-		ast_replace_subargument_delimiter(predial_string);
-	}
 
 	AST_LIST_LOCK(&dial->channels);
 	AST_LIST_TRAVERSE(&dial->channels, channel, list) {
@@ -449,10 +444,6 @@
 	int success = 0;
 	char *predial_string = dial->options[AST_DIAL_OPTION_PREDIAL];
 
-	if (!ast_strlen_zero(predial_string)) {
-		ast_replace_subargument_delimiter(predial_string);
-	}
-
 	/* Iterate through channel list, requesting and calling each one */
 	AST_LIST_LOCK(&dial->channels);
 	AST_LIST_TRAVERSE(&dial->channels, channel, list) {
@@ -471,10 +462,6 @@
 	char *tmp = ast_strdupa(ast_channel_call_forward(channel->owner));
 	char *tech = "Local", *device = tmp, *stuff;
 	char *predial_string = dial->options[AST_DIAL_OPTION_PREDIAL];
-
-	if (!ast_strlen_zero(predial_string)) {
-		ast_replace_subargument_delimiter(predial_string);
-	}
 
 	/* If call forwarding is disabled just drop the original channel and don't attempt to dial the new one */
 	if (FIND_RELATIVE_OPTION(dial, channel, AST_DIAL_OPTION_DISABLE_CALL_FORWARDING)) {

-- 
To view, visit https://gerrit.asterisk.org/1301
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: If53892b286d29f6cf955e2545b03dcffa2610981
Gerrit-PatchSet: 1
Gerrit-Project: asterisk
Gerrit-Branch: certified/13.1
Gerrit-Owner: Richard Mudgett <rmudgett at digium.com>
Gerrit-Reviewer: Anonymous Coward #1000019
Gerrit-Reviewer: Joshua Colp <jcolp at digium.com>
Gerrit-Reviewer: Kevin Harwell <kharwell at digium.com>



More information about the asterisk-code-review mailing list