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
This commit is contained in:
Jeff Peeler
2010-06-18 21:32:09 +00:00
parent 3f9c6bb3bc
commit 54f2dfc91c
3 changed files with 66 additions and 23 deletions

View File

@@ -143,7 +143,7 @@ void destroy_extensions(struct ael_extension *exten);
static void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct ael_extension *mother_exten, struct ast_context *context ); */ static void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct ael_extension *mother_exten, struct ast_context *context ); */
void set_priorities(struct ael_extension *exten); void set_priorities(struct ael_extension *exten);
void add_extensions(struct ael_extension *exten); void add_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);
void destroy_pval(pval *item); void destroy_pval(pval *item);
void destroy_pval_item(pval *item); void destroy_pval_item(pval *item);
int is_float(char *arg ); int is_float(char *arg );

View File

@@ -95,7 +95,7 @@ struct ael_extension *new_exten(void);
void destroy_extensions(struct ael_extension *exten); void destroy_extensions(struct ael_extension *exten);
void set_priorities(struct ael_extension *exten); void set_priorities(struct ael_extension *exten);
void add_extensions(struct ael_extension *exten); void add_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);
void destroy_pval(pval *item); void destroy_pval(pval *item);
void destroy_pval_item(pval *item); void destroy_pval_item(pval *item);
int is_float(char *arg ); int is_float(char *arg );
@@ -137,7 +137,11 @@ static int pbx_load_module(void)
if (errs == 0 && sem_err == 0) { if (errs == 0 && sem_err == 0) {
ast_log(LOG_NOTICE, "AEL load process: checked config file name '%s'.\n", rfilename); ast_log(LOG_NOTICE, "AEL load process: checked config file name '%s'.\n", rfilename);
local_table = ast_hashtab_create(11, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0); local_table = ast_hashtab_create(11, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0);
ast_compile_ael2(&local_contexts, local_table, parse_tree); if (ast_compile_ael2(&local_contexts, local_table, parse_tree)) {
ast_log(LOG_ERROR, "AEL compile failed! Aborting.\n");
destroy_pval(parse_tree); /* free up the memory */
return AST_MODULE_LOAD_DECLINE;
}
ast_log(LOG_NOTICE, "AEL load process: compiled config file name '%s'.\n", rfilename); ast_log(LOG_NOTICE, "AEL load process: compiled config file name '%s'.\n", rfilename);
ast_merge_contexts_and_delete(&local_contexts, local_table, registrar); ast_merge_contexts_and_delete(&local_contexts, local_table, registrar);

View File

@@ -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; pval *p,*p2,*p3;
struct ael_priority *pr; struct ael_priority *pr;
@@ -3345,10 +3345,10 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement,
#ifdef OLD_RAND_ACTION #ifdef OLD_RAND_ACTION
struct ael_priority *rand_test, *rand_end, *rand_skip; struct ael_priority *rand_test, *rand_end, *rand_skip;
#endif #endif
char buf1[2000]; char *buf1;
char buf2[2000]; char *buf2;
char *new_label;
char *strp, *strp2; char *strp, *strp2;
char new_label[2000];
int default_exists; int default_exists;
int local_control_statement_count; int local_control_statement_count;
int first; int first;
@@ -3356,6 +3356,16 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement,
struct ael_priority *loop_continue_save; struct ael_priority *loop_continue_save;
struct ael_extension *switch_case,*switch_null; 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 ((mother_exten && !mother_exten->checked_switch) || (exten && !exten->checked_switch)) {
if (contains_switch(statement)) { /* only run contains_switch if you haven't checked before */ if (contains_switch(statement)) { /* only run contains_switch if you haven't checked before */
if (mother_exten) { if (mother_exten) {
@@ -3633,7 +3643,9 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement,
exten->loop_break = for_end; exten->loop_break = for_end;
exten->loop_continue = for_inc; 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_inc, mother_exten);
linkprio(exten, for_loop, 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_break = while_end;
exten->loop_continue = while_test; 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_loop, mother_exten);
linkprio(exten, while_end, 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); switch_case->name = strdup(buf1);
snprintf(new_label,sizeof(new_label),"sw-%s-%s-%d", label, p2->u1.str, local_control_statement_count); 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... */ /* 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) { 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); switch_case->name = strdup(buf1);
snprintf(new_label,sizeof(new_label),"sw-%s-%s-%d", label, p2->u1.str, local_control_statement_count); 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... */ /* 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) { for (p3=p2->u2.statements; p3; p3=p3->next) {
if (!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); 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... */ /* 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) { 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 */ /* 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) { if (p->u3.else_statements) {
linkprio(exten, if_skip, mother_exten); 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); 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 */ /* 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) { if (p->u3.else_statements) {
linkprio(exten, if_skip, mother_exten); 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); linkprio(exten, if_end, mother_exten);
@@ -4136,7 +4162,9 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement,
break; break;
case PV_STATEMENTBLOCK: 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; break;
case PV_CATCH: 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); switch_case->name = strdup(p->u1.str);
snprintf(new_label,sizeof(new_label),"catch-%s-%d",p->u1.str, control_statement_count); 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 */ 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]; char buf[2000];
struct ael_priority *np2 = new_prio(); struct ael_priority *np2 = new_prio();
@@ -4175,6 +4205,10 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement,
break; break;
} }
} }
free(buf1);
free(buf2);
free(new_label);
return 0;
} }
void set_priorities(struct ael_extension *exten) 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; pval *p,*p2;
struct ast_context *context; 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... */ /* 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 */ if (exten->return_needed) { /* most likely, this will go away */
struct ael_priority *np2 = new_prio(); struct ael_priority *np2 = new_prio();
np2->type = AEL_APPCALL; 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 ) if ( p2->u3.hints )
exten->hints = strdup(p2->u3.hints); exten->hints = strdup(p2->u3.hints);
exten->regexten = p2->u4.regexten; 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) */ 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(); struct ael_priority *np2 = new_prio();
np2->type = AEL_APPCALL; 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 */ 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 */ destroy_extensions(exten_list); /* all that remains is an empty husk, discard of it as is proper */
return 0;
} }