Module: sip-router Branch: master Commit: 8637f3408456dcc4e2df2cf6b2530cc7f1588042 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=8637f340...
Author: Andrei Pelinescu-Onciul andrei@iptel.org Committer: Andrei Pelinescu-Onciul andrei@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;