aboutsummaryrefslogtreecommitdiffstats
path: root/pbx/pbx_ael.c
diff options
context:
space:
mode:
authormurf <murf@f38db490-d61c-443f-a65b-d21fe96a405b>2007-10-03 14:23:00 +0000
committermurf <murf@f38db490-d61c-443f-a65b-d21fe96a405b>2007-10-03 14:23:00 +0000
commit2c43029b2864b4befe2db02f5da03295ef5db0e1 (patch)
tree77c53f1593077d7549e95ae3553476aec4f4ee18 /pbx/pbx_ael.c
parent22d0a866a731dda20485e5c442a6b4761420f3cb (diff)
closes issue #10834 ; where a null input to a switch statement results in a hangup; since switch is implemented with extensions, and the default case is implemented with a '.', and the '.' matches 1 or more remaining characters, the case where 0 characters exist isn't matched, and the extension isn't matched, and the goto fails, and a hangup occurs. Now, when a default case is generated, it also generates a single fixed extension that will match a null input. That extension just does a goto to the default extension for that switch. I played with an alternate solution, where I just tack an extra char onto all the patterns and the goto, but not the default case's pattern. Then even a null input will still have at least one char in it. But it made me nervous, having that extra char in , even if that's a pretty secret and low-level issue.
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@84511 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'pbx/pbx_ael.c')
-rw-r--r--pbx/pbx_ael.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/pbx/pbx_ael.c b/pbx/pbx_ael.c
index eb86b5ab3..cf13d1628 100644
--- a/pbx/pbx_ael.c
+++ b/pbx/pbx_ael.c
@@ -2896,7 +2896,7 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement,
struct ael_priority *pr;
struct ael_priority *for_init, *for_test, *for_inc, *for_loop, *for_end;
struct ael_priority *while_test, *while_loop, *while_end;
- struct ael_priority *switch_test, *switch_end, *fall_thru;
+ struct ael_priority *switch_test, *switch_end, *fall_thru, *switch_empty;
struct ael_priority *if_test, *if_end, *if_skip, *if_false;
#ifdef OLD_RAND_ACTION
struct ael_priority *rand_test, *rand_end, *rand_skip;
@@ -2909,7 +2909,7 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement,
int local_control_statement_count;
struct ael_priority *loop_break_save;
struct ael_priority *loop_continue_save;
- struct ael_extension *switch_case;
+ struct ael_extension *switch_case,*switch_null;
for (p=statement; p; p=p->next) {
switch (p->type) {
@@ -3300,11 +3300,30 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement,
switch_case-> return_target = np2;
}
} else if (p2->type == PV_DEFAULT) {
- default_exists++;
/* ok, generate a extension and link it in */
switch_case = new_exten();
switch_case->context = this_context;
switch_case->is_switch = 1;
+
+ /* new: the default case intros a pattern with ., which covers ALMOST everything.
+ but it doesn't cover a NULL pattern. So, we'll define a null extension to match
+ that goto's the default extension. */
+
+ default_exists++;
+ switch_null = new_exten();
+ switch_null->context = this_context;
+ switch_null->is_switch = 1;
+ switch_empty = new_prio();
+ snprintf(buf1,sizeof(buf1),"sw-%d-.|10",local_control_statement_count);
+ switch_empty->app = strdup("Goto");
+ switch_empty->appargs = strdup(buf1);
+ linkprio(switch_null, switch_empty);
+ snprintf(buf1,sizeof(buf1),"sw-%d-", local_control_statement_count);
+ switch_null->name = strdup(buf1);
+ switch_null->loop_break = exten->loop_break;
+ switch_null->loop_continue = exten->loop_continue;
+ linkexten(exten,switch_null);
+
/* the break/continue locations are inherited from parent */
switch_case->loop_break = exten->loop_break;
switch_case->loop_continue = exten->loop_continue;
@@ -3314,7 +3333,7 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement,
snprintf(new_label,sizeof(new_label),"sw-%s-default-%d", label, local_control_statement_count);
- gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context); /* this will link in all the while body statements here */
+ gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context); /* this will link in all the default: body statements here */
/* here is where we write code to "fall thru" to the next case... if there is one... */
for (p3=p2->u2.statements; p3; p3=p3->next) {