Module: sip-router
Branch: master
Commit: 3856e9e81c8410b220b893a0dfe7114bba6bdc0d
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=3856e9e…
Author: Daniel-Constantin Mierla <miconda(a)gmail.com>
Committer: Daniel-Constantin Mierla <miconda(a)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) */
};