Module: sip-router Branch: master Commit: 3856e9e81c8410b220b893a0dfe7114bba6bdc0d URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=3856e9e8...
Author: Daniel-Constantin Mierla miconda@gmail.com Committer: Daniel-Constantin Mierla miconda@gmail.com Date: Sun Oct 27 16:59:32 2013 +0100
core: handle pv comparison with $null as when defined is used
- reported by Victor Seva, closes FS#358
---
cfg.y | 20 ++++++++++++++++++-- rvalue.c | 14 ++++++++++++++ rvalue.h | 1 + 3 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/cfg.y b/cfg.y index 3b7fbdd..2533f72 100644 --- a/cfg.y +++ b/cfg.y @@ -2756,8 +2756,24 @@ rval_expr: rval { $$=$1; | rval_expr BIN_LSHIFT rval_expr {$$=mk_rve2(RVE_BLSHIFT_OP, $1, $3);} | rval_expr BIN_RSHIFT rval_expr {$$=mk_rve2(RVE_BRSHIFT_OP, $1, $3);} | rval_expr rve_cmpop rval_expr %prec GT { $$=mk_rve2( $2, $1, $3);} - | rval_expr rve_equalop rval_expr %prec EQUAL_T - { $$=mk_rve2( $2, $1, $3);} + | rval_expr rve_equalop rval_expr %prec EQUAL_T { + /* comparing with $null => treat as defined or !defined */ + if($3->op==RVE_RVAL_OP && $3->left.rval.type==RV_PVAR + && $3->left.rval.v.pvs.type==PVT_NULL) { + if($2==RVE_DIFF_OP || $2==RVE_IDIFF_OP + || $2==RVE_STRDIFF_OP) { + DBG("comparison with $null switched to notdefined operator\n"); + $$=mk_rve1(RVE_DEFINED_OP, $1); + } else { + DBG("comparison with $null switched to defined operator\n"); + $$=mk_rve1(RVE_NOTDEFINED_OP, $1); + } + /* free rve struct for $null */ + rve_destroy($3); + } else { + $$=mk_rve2($2, $1, $3); + } + } | rval_expr LOG_AND rval_expr { $$=mk_rve2(RVE_LAND_OP, $1, $3);} | rval_expr LOG_OR rval_expr { $$=mk_rve2(RVE_LOR_OP, $1, $3);} | LPAREN rval_expr RPAREN { $$=$2;} diff --git a/rvalue.c b/rvalue.c index cb0db9c..ddc97c2 100644 --- a/rvalue.c +++ b/rvalue.c @@ -527,6 +527,7 @@ enum rval_type rve_guess_type( struct rval_expr* rve) case RVE_STRLEN_OP: case RVE_STREMPTY_OP: case RVE_DEFINED_OP: + case RVE_NOTDEFINED_OP: case RVE_INT_OP: return RV_INT; case RVE_PLUS_OP: @@ -572,6 +573,7 @@ int rve_is_constant(struct rval_expr* rve) case RVE_STRLEN_OP: case RVE_STREMPTY_OP: case RVE_DEFINED_OP: + case RVE_NOTDEFINED_OP: case RVE_INT_OP: case RVE_STR_OP: return rve_is_constant(rve->left.rve); @@ -636,6 +638,7 @@ static int rve_op_unary(enum rval_expr_op op) case RVE_STRLEN_OP: case RVE_STREMPTY_OP: case RVE_DEFINED_OP: + case RVE_NOTDEFINED_OP: case RVE_INT_OP: case RVE_STR_OP: return 1; @@ -839,6 +842,7 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve, case RVE_STRLEN_OP: case RVE_STREMPTY_OP: case RVE_DEFINED_OP: + case RVE_NOTDEFINED_OP: *type=RV_INT; if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){ if (type1==RV_INT){ @@ -2112,6 +2116,10 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg, case RVE_DEFINED_OP: ret=int_rve_defined(h, msg, res, rve->left.rve); break; + case RVE_NOTDEFINED_OP: + ret=int_rve_defined(h, msg, res, rve->left.rve); + *res = !(*res); + break; case RVE_STREQ_OP: case RVE_STRDIFF_OP: case RVE_MATCH_OP: @@ -2233,6 +2241,7 @@ int rval_expr_eval_rvint( struct run_act_ctx* h, case RVE_STRLEN_OP: case RVE_STREMPTY_OP: case RVE_DEFINED_OP: + case RVE_NOTDEFINED_OP: case RVE_INT_OP: /* operator forces integer type */ ret=rval_expr_eval_int(h, msg, res_i, rve); @@ -2360,6 +2369,7 @@ struct rvalue* rval_expr_eval(struct run_act_ctx* h, struct sip_msg* msg, case RVE_STRLEN_OP: case RVE_STREMPTY_OP: case RVE_DEFINED_OP: + case RVE_NOTDEFINED_OP: case RVE_INT_OP: /* operator forces integer type */ r=rval_expr_eval_int(h, msg, &i, rve); @@ -2601,6 +2611,7 @@ struct rval_expr* mk_rval_expr1(enum rval_expr_op op, struct rval_expr* rve1, case RVE_STRLEN_OP: case RVE_STREMPTY_OP: case RVE_DEFINED_OP: + case RVE_NOTDEFINED_OP: case RVE_INT_OP: case RVE_STR_OP: break; @@ -2692,6 +2703,7 @@ static int rve_op_is_assoc(enum rval_expr_op op) case RVE_STRLEN_OP: case RVE_STREMPTY_OP: case RVE_DEFINED_OP: + case RVE_NOTDEFINED_OP: case RVE_INT_OP: case RVE_STR_OP: /* one operand expression => cannot be assoc. */ @@ -2747,6 +2759,7 @@ static int rve_op_is_commutative(enum rval_expr_op op) case RVE_STRLEN_OP: case RVE_STREMPTY_OP: case RVE_DEFINED_OP: + case RVE_NOTDEFINED_OP: case RVE_INT_OP: case RVE_STR_OP: /* one operand expression => cannot be commut. */ @@ -3796,6 +3809,7 @@ int fix_rval_expr(void* p) case RVE_STRLEN_OP: case RVE_STREMPTY_OP: case RVE_DEFINED_OP: + case RVE_NOTDEFINED_OP: case RVE_INT_OP: case RVE_STR_OP: ret=fix_rval_expr((void*)rve->left.rve); diff --git a/rvalue.h b/rvalue.h index 14675af..c0c2e0e 100644 --- a/rvalue.h +++ b/rvalue.h @@ -87,6 +87,7 @@ enum rval_expr_op{ RVE_MATCH_OP, /**< 2 members, string ~), returns left matches re(right) */ /* avp, pvars a.s.o */ RVE_DEFINED_OP, /**< one member, returns is_defined(val) (bool) */ + RVE_NOTDEFINED_OP, /**< one member, returns is_not_defined(val) (bool) */ RVE_INT_OP, /**< one member, returns (int)val (int) */ RVE_STR_OP /**< one member, returns (str)val (str) */ };