Browse code

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.

Andrei Pelinescu-Onciul authored on 29/09/2010 14:30:40
Showing 5 changed files
... ...
@@ -1564,7 +1564,8 @@ int run_actions(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
1564 1564
 	h->rec_lev--;
1565 1565
 end:
1566 1566
 	/* process module onbreak handlers if present */
1567
-	if (unlikely(h->rec_lev==0 && ret==0))
1567
+	if (unlikely(h->rec_lev==0 && ret==0 &&
1568
+					!(h->run_flags & IGNORE_ON_BREAK_R_F)))
1568 1569
 		for (mod=modules;mod;mod=mod->next)
1569 1570
 			if (unlikely(mod->exports.onbreak_f)) {
1570 1571
 				mod->exports.onbreak_f( msg );
... ...
@@ -1578,6 +1579,33 @@ error:
1578 1578
 }
1579 1579
 
1580 1580
 
1581
+
1582
+#ifdef USE_LONGJMP
1583
+/** safe version of run_actions().
1584
+ * It always return (it doesn't longjmp on forced script end).
1585
+ * @returns 0, or 1 on success, <0 on error
1586
+ * (0 if drop or break encountered, 1 if not ) */
1587
+int run_actions_safe(struct run_act_ctx* h, struct action* a,
1588
+						struct sip_msg* msg)
1589
+{
1590
+	struct run_act_ctx ctx;
1591
+	int ret;
1592
+	int ign_on_break;
1593
+	
1594
+	/* start with a fresh action context */
1595
+	init_run_actions_ctx(&ctx);
1596
+	ctx.last_retcode = h->last_retcode;
1597
+	ign_on_break = h->run_flags & IGNORE_ON_BREAK_R_F;
1598
+	ctx.run_flags = h->run_flags | IGNORE_ON_BREAK_R_F;
1599
+	ret = run_actions(&ctx, a, msg);
1600
+	h->last_retcode = ctx.last_retcode;
1601
+	h->run_flags = (ctx.run_flags & ~IGNORE_ON_BREAK_R_F) | ign_on_break;
1602
+	return ret;
1603
+}
1604
+#endif /* USE_LONGJMP */
1605
+
1606
+
1607
+
1581 1608
 int run_top_route(struct action* a, sip_msg_t* msg, struct run_act_ctx *c)
1582 1609
 {
1583 1610
 	struct run_act_ctx ctx;
... ...
@@ -68,4 +68,12 @@ int run_actions(struct run_act_ctx* c, struct action* a, struct sip_msg* msg);
68 68
 
69 69
 int run_top_route(struct action* a, sip_msg_t* msg, struct run_act_ctx* c);
70 70
 
71
+
72
+#ifdef USE_LONGJMP
73
+int run_actions_safe(struct run_act_ctx* c, struct action* a,
74
+						struct sip_msg* msg);
75
+#else /*! USE_LONGJMP */
76
+#define run_actions_safe(c, a, m) run_actions(c, a, m)
77
+#endif /* USE_LONGJMP */
78
+
71 79
 #endif
... ...
@@ -108,7 +108,7 @@ inline static int lval_avp_assign(struct run_act_ctx* h, struct sip_msg* msg,
108 108
 		case RV_ACTION_ST:
109 109
 			flags=avp->type & ~AVP_VAL_STR;
110 110
 			if (rv->v.action)
111
-				value.n=run_actions(h, rv->v.action, msg);
111
+				value.n=run_actions_safe(h, rv->v.action, msg);
112 112
 			else
113 113
 				value.n=-1;
114 114
 			ret=value.n;
... ...
@@ -283,7 +283,7 @@ inline static int lval_pvar_assign(struct run_act_ctx* h, struct sip_msg* msg,
283 283
 		case RV_ACTION_ST:
284 284
 			pval.flags=PV_TYPE_INT|PV_VAL_INT;
285 285
 			if (rv->v.action)
286
-				pval.ri=run_actions(h, rv->v.action, msg);
286
+				pval.ri=run_actions_safe(h, rv->v.action, msg);
287 287
 			else
288 288
 				pval.ri=0;
289 289
 			ret=pval.ri;
... ...
@@ -142,6 +142,7 @@ typedef enum _operand_subtype action_param_type;
142 142
 #define RETURN_R_F 2
143 143
 #define BREAK_R_F  4
144 144
 #define DROP_R_F   8
145
+#define IGNORE_ON_BREAK_R_F 256
145 146
 
146 147
 
147 148
 struct cfg_pos{
... ...
@@ -901,7 +901,7 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
901 901
 			break;
902 902
 		case RV_ACTION_ST:
903 903
 			if (rv->v.action)
904
-				*i=(run_actions(h, rv->v.action, msg)>0);
904
+				*i=(run_actions_safe(h, rv->v.action, msg)>0);
905 905
 			else
906 906
 				*i=0;
907 907
 			break;
... ...
@@ -1100,7 +1100,7 @@ int rval_get_tmp_str(struct run_act_ctx* h, struct sip_msg* msg,
1100 1100
 			break;
1101 1101
 		case RV_ACTION_ST:
1102 1102
 			if (rv->v.action)
1103
-				i=(run_actions(h, rv->v.action, msg)>0);
1103
+				i=(run_actions_safe(h, rv->v.action, msg)>0);
1104 1104
 			else
1105 1105
 				i=0;
1106 1106
 			tmpv->s=sint2strbuf(i, tmp_cache->i2s,