Răsfoiți Sursa

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)
Andrei Pelinescu-Onciul 15 ani în urmă
părinte
comite
8eb41afc97
5 a modificat fișierele cu 42 adăugiri și 5 ștergeri
  1. 29 1
      action.c
  2. 8 0
      action.h
  3. 2 2
      lvalue.c
  4. 1 0
      route_struct.h
  5. 2 2
      rvalue.c

+ 29 - 1
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;

+ 8 - 0
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

+ 2 - 2
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;

+ 1 - 0
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{

+ 2 - 2
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);