Module: sip-router
Branch: master
Commit: 28a882873f8a69a189d790e33bcd2017c253a66a
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=28a8828…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)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.
---
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 dd0cfef..1716c34 100644
--- a/action.c
+++ b/action.c
@@ -1564,7 +1564,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 (unlikely(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 (unlikely(mod->exports.onbreak_f)) {
mod->exports.onbreak_f( msg );
@@ -1578,6 +1579,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 c11baa9..a2a5395 100644
--- a/action.h
+++ b/action.h
@@ -68,4 +68,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 4610da4..47a625f 100644
--- a/lvalue.c
+++ b/lvalue.c
@@ -108,7 +108,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;
@@ -283,7 +283,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 2d4a643..16733db 100644
--- a/route_struct.h
+++ b/route_struct.h
@@ -142,6 +142,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 eeac3d5..6ef399b 100644
--- a/rvalue.c
+++ b/rvalue.c
@@ -901,7 +901,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;
@@ -1100,7 +1100,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=sint2strbuf(i, tmp_cache->i2s,