diff options
author | murf <murf@f38db490-d61c-443f-a65b-d21fe96a405b> | 2007-10-03 14:39:05 +0000 |
---|---|---|
committer | murf <murf@f38db490-d61c-443f-a65b-d21fe96a405b> | 2007-10-03 14:39:05 +0000 |
commit | 8a8a482e0591c898f35188eea491d026b1657c2b (patch) | |
tree | e9211abc8defa8320abea1cc6105e0d14e3596f0 /res/ael | |
parent | b26d058476457592a2cbcefcc9ee8028952c1a66 (diff) |
Merged revisions 84511 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
r84511 | murf | 2007-10-03 08:23:00 -0600 (Wed, 03 Oct 2007) | 1 line
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/trunk@84512 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'res/ael')
-rw-r--r-- | res/ael/pval.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/res/ael/pval.c b/res/ael/pval.c index 960c3eca5..b53f9fef9 100644 --- a/res/ael/pval.c +++ b/res/ael/pval.c @@ -3038,7 +3038,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; @@ -3052,7 +3052,7 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, int first; 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) { @@ -3451,11 +3451,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; @@ -3465,7 +3484,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) { |