From 54f2dfc91c9eedce4a6abb13126fc0b696a6d5ef Mon Sep 17 00:00:00 2001 From: Jeff Peeler Date: Fri, 18 Jun 2010 21:32:09 +0000 Subject: Merged revisions 271399 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r271399 | jpeeler | 2010-06-18 14:28:24 -0500 (Fri, 18 Jun 2010) | 11 lines Fix crash when parsing some heavily nested statements in AEL on reload. Due to the recursion used when compiling AEL in gen_prios, all the stack space was being consumed when parsing some AEL that contained nesting 13 levels deep. Changing a few large buffers to be heap allocated fixed the crash, although I did not test how many more levels can now be safely used. (closes issue #16053) Reported by: diLLec Tested by: jpeeler ........ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@271483 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- res/ael/pval.c | 79 +++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 59 insertions(+), 20 deletions(-) (limited to 'res/ael') diff --git a/res/ael/pval.c b/res/ael/pval.c index 5414e7971..e2ef9f5a5 100644 --- a/res/ael/pval.c +++ b/res/ael/pval.c @@ -3334,7 +3334,7 @@ int contains_switch(pval *item) } -static void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct ael_extension *mother_exten, struct ast_context *this_context ) +static int gen_prios(struct ael_extension *exten, char *label, pval *statement, struct ael_extension *mother_exten, struct ast_context *this_context ) { pval *p,*p2,*p3; struct ael_priority *pr; @@ -3345,16 +3345,26 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, #ifdef OLD_RAND_ACTION struct ael_priority *rand_test, *rand_end, *rand_skip; #endif - char buf1[2000]; - char buf2[2000]; + char *buf1; + char *buf2; + char *new_label; char *strp, *strp2; - char new_label[2000]; int default_exists; int local_control_statement_count; int first; struct ael_priority *loop_break_save; struct ael_priority *loop_continue_save; struct ael_extension *switch_case,*switch_null; + + if (!(buf1 = malloc(2000))) { + return -1; + } + if (!(buf2 = malloc(2000))) { + return -1; + } + if (!(new_label = malloc(2000))) { + return -1; + } if ((mother_exten && !mother_exten->checked_switch) || (exten && !exten->checked_switch)) { if (contains_switch(statement)) { /* only run contains_switch if you haven't checked before */ @@ -3633,7 +3643,9 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, exten->loop_break = for_end; exten->loop_continue = for_inc; - gen_prios(exten, new_label, p->u4.for_statements, mother_exten, this_context); /* this will link in all the statements here */ + if (gen_prios(exten, new_label, p->u4.for_statements, mother_exten, this_context)) { /* this will link in all the statements here */ + return -1; + } linkprio(exten, for_inc, mother_exten); linkprio(exten, for_loop, mother_exten); @@ -3671,7 +3683,9 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, exten->loop_break = while_end; exten->loop_continue = while_test; - gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context); /* this will link in all the while body statements here */ + if (gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context)) { /* this will link in all the while body statements here */ + return -1; + } linkprio(exten, while_loop, mother_exten); linkprio(exten, while_end, mother_exten); @@ -3732,7 +3746,9 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, switch_case->name = strdup(buf1); snprintf(new_label,sizeof(new_label),"sw-%s-%s-%d", label, p2->u1.str, local_control_statement_count); - gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context); /* this will link in all the case body statements here */ + if (gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context)) { /* this will link in all the case body statements here */ + return -1; + } /* 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) { @@ -3804,7 +3820,9 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, switch_case->name = strdup(buf1); snprintf(new_label,sizeof(new_label),"sw-%s-%s-%d", label, p2->u1.str, 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 */ + if (gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context)) { /* this will link in all the while body statements here */ + return -1; + } /* 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) { if (!p3->next) @@ -3903,7 +3921,9 @@ 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 default: body statements here */ + if (gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context)) { /* this will link in all the default: body statements here */ + return -1; + } /* 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) { @@ -4076,12 +4096,15 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, /* now, put the body of the if here */ - gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context); /* this will link in all the statements here */ + if (gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context)) { /* this will link in all the statements here */ + return -1; + } if (p->u3.else_statements) { linkprio(exten, if_skip, mother_exten); - gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context); /* this will link in all the statements here */ - + if (gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context)) { /* this will link in all the statements here */ + return -1; + } } linkprio(exten, if_end, mother_exten); @@ -4123,12 +4146,15 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, /* now, put the body of the if here */ - gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context); /* this will link in all the statements here */ + if (gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context)) { /* this will link in all the statements here */ + return -1; + } if (p->u3.else_statements) { linkprio(exten, if_skip, mother_exten); - gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context); /* this will link in all the statements here */ - + if (gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context)) { /* this will link in all the statements here */ + return -1; + } } linkprio(exten, if_end, mother_exten); @@ -4136,7 +4162,9 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, break; case PV_STATEMENTBLOCK: - gen_prios(exten, label, p->u1.list, mother_exten, this_context ); /* recurse into the block */ + if (gen_prios(exten, label, p->u1.list, mother_exten, this_context)) { /* recurse into the block */ + return -1; + } break; case PV_CATCH: @@ -4158,7 +4186,9 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, switch_case->name = strdup(p->u1.str); snprintf(new_label,sizeof(new_label),"catch-%s-%d",p->u1.str, control_statement_count); - gen_prios(switch_case, new_label, p->u2.statements,mother_exten,this_context); /* this will link in all the catch body statements here */ + if (gen_prios(switch_case, new_label, p->u2.statements, mother_exten,this_context)) { /* this will link in all the catch body statements here */ + return -1; + } if (switch_case->return_needed) { /* returns now generate a Return() app call, no longer a goto to the end of the exten */ char buf[2000]; struct ael_priority *np2 = new_prio(); @@ -4175,6 +4205,10 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, break; } } + free(buf1); + free(buf2); + free(new_label); + return 0; } void set_priorities(struct ael_extension *exten) @@ -4389,7 +4423,7 @@ static void fix_gotos_in_extensions(struct ael_extension *exten) } -void ast_compile_ael2(struct ast_context **local_contexts, struct ast_hashtab *local_table, struct pval *root) +int ast_compile_ael2(struct ast_context **local_contexts, struct ast_hashtab *local_table, struct pval *root) { pval *p,*p2; struct ast_context *context; @@ -4442,7 +4476,9 @@ void ast_compile_ael2(struct ast_context **local_contexts, struct ast_hashtab *l } /* CONTAINS APPCALLS, CATCH, just like extensions... */ - gen_prios(exten, p->u1.str, p->u3.macro_statements, 0, context ); + if (gen_prios(exten, p->u1.str, p->u3.macro_statements, 0, context)) { + return -1; + } if (exten->return_needed) { /* most likely, this will go away */ struct ael_priority *np2 = new_prio(); np2->type = AEL_APPCALL; @@ -4484,7 +4520,9 @@ void ast_compile_ael2(struct ast_context **local_contexts, struct ast_hashtab *l if ( p2->u3.hints ) exten->hints = strdup(p2->u3.hints); exten->regexten = p2->u4.regexten; - gen_prios(exten, p->u1.str, p2->u2.statements, 0, context ); + if (gen_prios(exten, p->u1.str, p2->u2.statements, 0, context)) { + return -1; + } if (exten->return_needed) { /* returns don't generate a goto eoe (end of extension) any more, just a Return() app call) */ struct ael_priority *np2 = new_prio(); np2->type = AEL_APPCALL; @@ -4572,6 +4610,7 @@ void ast_compile_ael2(struct ast_context **local_contexts, struct ast_hashtab *l add_extensions(exten_list); /* actually makes calls to create priorities in ast_contexts -- feeds dialplan to asterisk */ destroy_extensions(exten_list); /* all that remains is an empty husk, discard of it as is proper */ + return 0; } -- cgit v1.2.3