Module: sip-router Branch: kamailio_3.0 Commit: 8eb41afc974a4bd0a1a6346240ace0ff72f89279 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=8eb41afc...
Author: Andrei Pelinescu-Onciul andrei@iptel.org Committer: Andrei Pelinescu-Onciul andrei@iptel.org Date: Wed Sep 29 16:30:40 2010 +0200
core: fix end-script commands in expr. leaks
When having commands that end the script immediately in assignments (e.g. $foo = { drop; }) or in expressions (e.g. if ($v + { drop; } > 0)), the script was terminated immediately via longjmp. However this might leave some un-freed variables. This fix introduces a safe version of run_actions() (run_actions_safe()) that will not use longjmp() to immediately end the whole script on drop, returning instead to its caller. (cherry picked from commit 28a882873f8a69a189d790e33bcd2017c253a66a)
---
action.c | 30 +++++++++++++++++++++++++++++- action.h | 8 ++++++++ lvalue.c | 4 ++-- route_struct.h | 1 + rvalue.c | 4 ++-- 5 files changed, 42 insertions(+), 5 deletions(-)
diff --git a/action.c b/action.c index db71a15..9a2aad7 100644 --- a/action.c +++ b/action.c @@ -1331,7 +1331,8 @@ int run_actions(struct run_act_ctx* h, struct action* a, struct sip_msg* msg) h->rec_lev--; end: /* process module onbreak handlers if present */ - if (h->rec_lev==0 && ret==0) + if (unlikely(h->rec_lev==0 && ret==0 && + !(h->run_flags & IGNORE_ON_BREAK_R_F))) for (mod=modules;mod;mod=mod->next) if ((mod->mod_interface_ver==0) && mod->exports && mod->exports->v0.onbreak_f) { @@ -1348,6 +1349,33 @@ error: }
+ +#ifdef USE_LONGJMP +/** safe version of run_actions(). + * It always return (it doesn't longjmp on forced script end). + * @returns 0, or 1 on success, <0 on error + * (0 if drop or break encountered, 1 if not ) */ +int run_actions_safe(struct run_act_ctx* h, struct action* a, + struct sip_msg* msg) +{ + struct run_act_ctx ctx; + int ret; + int ign_on_break; + + /* start with a fresh action context */ + init_run_actions_ctx(&ctx); + ctx.last_retcode = h->last_retcode; + ign_on_break = h->run_flags & IGNORE_ON_BREAK_R_F; + ctx.run_flags = h->run_flags | IGNORE_ON_BREAK_R_F; + ret = run_actions(&ctx, a, msg); + h->last_retcode = ctx.last_retcode; + h->run_flags = (ctx.run_flags & ~IGNORE_ON_BREAK_R_F) | ign_on_break; + return ret; +} +#endif /* USE_LONGJMP */ + + + int run_top_route(struct action* a, sip_msg_t* msg, struct run_act_ctx *c) { struct run_act_ctx ctx; diff --git a/action.h b/action.h index c07b9ae..c4c0856 100644 --- a/action.h +++ b/action.h @@ -61,4 +61,12 @@ int run_actions(struct run_act_ctx* c, struct action* a, struct sip_msg* msg);
int run_top_route(struct action* a, sip_msg_t* msg, struct run_act_ctx* c);
+ +#ifdef USE_LONGJMP +int run_actions_safe(struct run_act_ctx* c, struct action* a, + struct sip_msg* msg); +#else /*! USE_LONGJMP */ +#define run_actions_safe(c, a, m) run_actions(c, a, m) +#endif /* USE_LONGJMP */ + #endif diff --git a/lvalue.c b/lvalue.c index 2db1ba9..4f4e501 100644 --- a/lvalue.c +++ b/lvalue.c @@ -101,7 +101,7 @@ inline static int lval_avp_assign(struct run_act_ctx* h, struct sip_msg* msg, case RV_ACTION_ST: flags=avp->type & ~AVP_VAL_STR; if (rv->v.action) - value.n=run_actions(h, rv->v.action, msg); + value.n=run_actions_safe(h, rv->v.action, msg); else value.n=-1; ret=value.n; @@ -276,7 +276,7 @@ inline static int lval_pvar_assign(struct run_act_ctx* h, struct sip_msg* msg, case RV_ACTION_ST: pval.flags=PV_TYPE_INT|PV_VAL_INT; if (rv->v.action) - pval.ri=run_actions(h, rv->v.action, msg); + pval.ri=run_actions_safe(h, rv->v.action, msg); else pval.ri=0; ret=pval.ri; diff --git a/route_struct.h b/route_struct.h index 3f7e854..1edaad8 100644 --- a/route_struct.h +++ b/route_struct.h @@ -134,6 +134,7 @@ typedef enum _operand_subtype action_param_type; #define RETURN_R_F 2 #define BREAK_R_F 4 #define DROP_R_F 8 +#define IGNORE_ON_BREAK_R_F 256
struct cfg_pos{ diff --git a/rvalue.c b/rvalue.c index b17e664..f9ba65c 100644 --- a/rvalue.c +++ b/rvalue.c @@ -894,7 +894,7 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg, break; case RV_ACTION_ST: if (rv->v.action) - *i=(run_actions(h, rv->v.action, msg)>0); + *i=(run_actions_safe(h, rv->v.action, msg)>0); else *i=0; break; @@ -1089,7 +1089,7 @@ int rval_get_tmp_str(struct run_act_ctx* h, struct sip_msg* msg, break; case RV_ACTION_ST: if (rv->v.action) - i=(run_actions(h, rv->v.action, msg)>0); + i=(run_actions_safe(h, rv->v.action, msg)>0); else i=0; tmpv->s=int2str(i, &tmpv->len);