Module: sip-router
Branch: master
Commit: 8637f3408456dcc4e2df2cf6b2530cc7f1588042
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=8637f34…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Date: Mon May 4 21:58:40 2009 +0200
core script engine: if switched to rval_expr
- switched if to use directly rval_expr
- warn on startup if "if" expression is constant
- fail to start if "if" expression evaluates to non-int
---
action.c | 23 +++++++--------------
cfg.y | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
route.c | 42 +++++++++++++++++++++++++++++++++------
3 files changed, 104 insertions(+), 26 deletions(-)
diff --git a/action.c b/action.c
index ffc0051..f99079a 100644
--- a/action.c
+++ b/action.c
@@ -49,6 +49,7 @@
* 2008-11-18 support for variable parameter module functions (andrei)
* 2008-12-03 use lvalues/rvalues for assignments (andrei)
* 2008-12-17 added UDP_MTU_TRY_PROTO_T (andrei)
+ * 2009-05-04 switched IF_T to rval_expr (andrei)
*/
@@ -813,21 +814,14 @@ int do_action(struct run_act_ctx* h, struct action* a, struct
sip_msg* msg)
ret=1;
break;
case IF_T:
- /* if null expr => ignore if? */
- if ((a->val[0].type==EXPR_ST)&&a->val[0].u.data){
- v=eval_expr(h, (struct expr*)a->val[0].u.data, msg);
-#if 0
- if (v<0){
- if (v==EXPR_DROP){ /* hack to quit on DROP*/
- ret=0;
- break;
- }else{
- LOG(L_WARN,"WARNING: do_action:"
- "error in expression\n");
- }
+ rve=(struct rval_expr*)a->val[0].u.data;
+ if (unlikely(rval_expr_eval_int(h, msg, &v, rve) != 0)){
+ ERR("if expression evaluation failed (%d,%d-%d,%d)\n",
+ rve->fpos.s_line, rve->fpos.s_col,
+ rve->fpos.e_line, rve->fpos.e_col);
+ v=0; /* false */
}
-#endif
- if (h->run_flags & EXIT_R_F){
+ if (unlikely(h->run_flags & EXIT_R_F)){
ret=0;
break;
}
@@ -843,7 +837,6 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg*
msg)
ret=run_actions(h,
(struct action*)a->val[2].u.data, msg);
}
- }
break;
case MODULE_T:
if ( a->val[0].type==MODEXP_ST && a->val[0].u.data &&
diff --git a/cfg.y b/cfg.y
index 5c0c3f2..21e81a1 100644
--- a/cfg.y
+++ b/cfg.y
@@ -95,6 +95,7 @@
* NUMBER is now always positive; cleanup (andrei)
* 2009-01-26 case/switch() support (andrei)
* 2009-03-10 added SET_USERPHONE action (Miklos)
+ * 2009-05-04 switched if to rval_expr (andrei)
*/
%{
@@ -212,6 +213,8 @@ static struct rval_expr* mk_rve_rval(enum rval_type, void* v);
static struct rval_expr* mk_rve1(enum rval_expr_op op, struct rval_expr* rve1);
static struct rval_expr* mk_rve2(enum rval_expr_op op, struct rval_expr* rve1,
struct rval_expr* rve2);
+static int rval_expr_int_check(struct rval_expr *rve);
+static int warn_ct_rve(struct rval_expr *rve, char* name);
static struct socket_id* mk_listen_id(char*, int, int);
static struct name_lst* mk_name_lst(char* name, int flags);
static struct socket_id* mk_listen_id2(struct name_lst*, int, int);
@@ -520,7 +523,8 @@ static int case_check_default(struct case_stms* stms);
/*non-terminals */
-%type <expr> exp exp_elem
+/*%type <expr> exp */
+%type <expr> exp_elem
%type <intval> intno eint_op eint_op_onsend
%type <intval> eip_op eip_op_onsend
%type <action> action actions cmd fcmd if_cmd stm /*exp_stm*/ assign_action
@@ -1566,7 +1570,7 @@ send_route_stm: ROUTE_SEND LBRACE actions RBRACE {
| ROUTE_SEND error { yyerror("invalid onsend_route statement"); }
;
-exp: rval_expr
+/*exp: rval_expr
{
if ($1==0){
yyerror("invalid expression");
@@ -1581,6 +1585,7 @@ exp: rval_expr
$$=mk_elem(NO_OP, RVEXP_O, $1, 0, 0);
}
;
+*/
/* exp elem operators */
equalop:
@@ -1852,8 +1857,18 @@ action:
| fcmd error { $$=0; yyerror("bad command: missing ';'?"); }
;
if_cmd:
- IF exp stm { $$=mk_action( IF_T, 3, EXPR_ST, $2, ACTIONS_ST, $3, NOSUBTYPE, 0); }
- | IF exp stm ELSE stm { $$=mk_action( IF_T, 3, EXPR_ST, $2, ACTIONS_ST, $3, ACTIONS_ST,
$5); }
+ IF rval_expr stm {
+ if (rval_expr_int_check($2)==0){
+ warn_ct_rve($2, "if");
+ }
+ $$=mk_action( IF_T, 3, RVE_ST, $2, ACTIONS_ST, $3, NOSUBTYPE, 0);
+ }
+ | IF rval_expr stm ELSE stm {
+ if (rval_expr_int_check($2)==0){
+ warn_ct_rve($2, "if");
+ }
+ $$=mk_action( IF_T, 3, RVE_ST, $2, ACTIONS_ST, $3, ACTIONS_ST, $5);
+ }
;
ct_rval: rval_expr {
@@ -2930,6 +2945,48 @@ static struct rval_expr* mk_rve2(enum rval_expr_op op, struct
rval_expr* rve1,
}
+/** check if the expression is an int.
+ * if the expression does not evaluate to an int return -1 and
+ * log an error.
+ * @return 0 on success, -1 on error */
+static int rval_expr_int_check(struct rval_expr *rve)
+{
+ struct rval_expr* bad_rve;
+ enum rval_type type, bad_t, exp_t;
+
+ if (rve==0){
+ yyerror("invalid expression");
+ return -1;
+ }else if (!rve_check_type(&type, rve, &bad_rve, &bad_t ,&exp_t)){
+ if (bad_rve)
+ yyerror_at(&rve->fpos, "bad expression: type mismatch:"
+ " %s instead of %s at (%d,%d)",
+ rval_type_name(bad_t), rval_type_name(exp_t),
+ bad_rve->fpos.s_line, bad_rve->fpos.s_col);
+ else
+ yyerror("BUG: unexpected null \"bad\" expression\n");
+ return -1;
+ }else if (type!=RV_INT && type!=RV_NONE){
+ yyerror_at(&rve->fpos, "invalid expression type, int expected\n");
+ return -1;
+ }
+ return 0;
+}
+
+
+/** warn if the expression is constant.
+ * @return 0 on success (no warning), 1 when warning */
+static int warn_ct_rve(struct rval_expr *rve, char* name)
+{
+ if (rve && rve_is_constant(rve)){
+ warn_at(&rve->fpos, "constant value in %s%s",
+ name?name:"expression", name?"(...)":"");
+ return 1;
+ }
+ return 0;
+}
+
+
static struct name_lst* mk_name_lst(char* host, int flags)
{
struct name_lst* l;
diff --git a/route.c b/route.c
index 7b831e2..4ba116a 100644
--- a/route.c
+++ b/route.c
@@ -49,6 +49,7 @@
* 2008-04-23 errors are treated as false during expression evaluation
* unless the operator is DIFF_OP (Miklos)
* 2008-12-03 fixups for rvalues in assignments (andrei)
+ * 2009-05-04 switched IF_T to rval_expr (andrei)
*/
@@ -674,24 +675,50 @@ int fix_actions(struct action* a)
}
break;
case IF_T:
- if (t->val[0].type!=EXPR_ST){
+ if (t->val[0].type!=RVE_ST){
LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
- "%d for if (should be expr)\n",
+ "%d for if (should be rval expr)\n",
t->val[0].type);
return E_BUG;
- }else if( (t->val[1].type!=ACTIONS_ST)&&(t->val[1].type!=NOSUBTYPE) ){
+ }else if( (t->val[1].type!=ACTIONS_ST) &&
+ (t->val[1].type!=NOSUBTYPE) ){
LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
"%d for if() {...} (should be action)\n",
t->val[1].type);
return E_BUG;
- }else if( (t->val[2].type!=ACTIONS_ST)&&(t->val[2].type!=NOSUBTYPE) ){
+ }else if( (t->val[2].type!=ACTIONS_ST) &&
+ (t->val[2].type!=NOSUBTYPE) ){
LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
"%d for if() {} else{...}(should be action)\n",
t->val[2].type);
return E_BUG;
}
- if (t->val[0].u.data){
- if ((ret=fix_expr((struct expr*)t->val[0].u.data))<0)
+ rve=(struct rval_expr*)t->val[0].u.data;
+ if (rve){
+ err_rve=0;
+ if (!rve_check_type(&rve_type, rve, &err_rve,
+ &err_type, &expected_type)){
+ if (err_rve)
+ LOG(L_ERR, "fix_actions: invalid expression "
+ "(%d,%d): subexpression (%d,%d) has type"
+ " %s, but %s is expected\n",
+ rve->fpos.s_line, rve->fpos.s_col,
+ err_rve->fpos.s_line, err_rve->fpos.s_col,
+ rval_type_name(err_type),
+ rval_type_name(expected_type) );
+ else
+ LOG(L_ERR, "fix_actions: invalid expression "
+ "(%d,%d): type mismatch?",
+ rve->fpos.s_line, rve->fpos.s_col);
+ return E_UNSPEC;
+ }
+ if (rve_type!=RV_INT && rve_type!=RV_NONE){
+ LOG(L_ERR, "fix_actions: invalid expression (%d,%d):"
+ " bad type, integer expected\n",
+ rve->fpos.s_line, rve->fpos.s_col);
+ return E_UNSPEC;
+ }
+ if ((ret=fix_rval_expr((void**)&rve))<0)
return ret;
}
if ( (t->val[1].type==ACTIONS_ST)&&(t->val[1].u.data) ){
@@ -699,7 +726,8 @@ int fix_actions(struct action* a)
return ret;
}
if ( (t->val[2].type==ACTIONS_ST)&&(t->val[2].u.data) ){
- if ((ret=fix_actions((struct action*)t->val[2].u.data))<0)
+ if ((ret=fix_actions((struct action*)t->val[2].u.data))
+ <0)
return ret;
}
break;