Index: apps/app_macro.c =================================================================== --- apps/app_macro.c (revision 60711) +++ apps/app_macro.c (working copy) @@ -145,10 +145,11 @@ int res=0; char oldexten[256]=""; int oldpriority, gosub_level = 0; - char pc[80], depthc[12]; + char pc[80], depthc[12], stackheadc[sizeof(void *) * 11 / 4 + 1]; char oldcontext[AST_MAX_CONTEXT] = ""; char *offsets, *s, *inhangupc; int offset, depth = 0, maxdepth = 7; + void *stackhead; int setmacrocontext=0; int autoloopflag, dead = 0, inhangup = 0; @@ -181,6 +182,19 @@ depth = 0; } + /* Since people keep finding new ways to overflow the stack with Macro, + * here is a new approach to avoid future crashes -- just count the amount + * of stack used so far and return before we near our limit. + */ + tmp = pbx_builtin_getvar_helper(chan, "MACRO_STACKHEAD"); + if (tmp) { + sscanf(tmp, "%p", &stackhead); + } else { + stackhead = &tmp; + snprintf(stackheadc, sizeof(stackheadc), "%p", stackhead); + pbx_builtin_setvar_helper(chan, "MACRO_STACKHEAD", stackheadc); + } + /* Used for detecting whether to return when a Macro is called from another Macro after hangup */ if (strcmp(chan->exten, "h") == 0) pbx_builtin_setvar_helper(chan, "MACRO_IN_HANGUP", "1"); @@ -193,6 +207,17 @@ LOCAL_USER_REMOVE(u); return 0; } + + /* 200,000 is an arbitrary number lower than 240k, which is the current + * per-thread stack size. Also, we abs() the value, so that it doesn't + * matter which way the stack grows (per arch). + */ + if (abs((long)&tmp - (long)stackhead) > 200000L) { + ast_log(LOG_ERROR, "Macro(): you have consumed too much per-thread stack space. Returning early to avoid a possible crash.\n"); + LOCAL_USER_REMOVE(u); + return 0; + } + snprintf(depthc, sizeof(depthc), "%d", depth + 1); pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);