Browse code

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

Andrei Pelinescu-Onciul authored on 04/05/2009 19:58:40
Showing 3 changed files
... ...
@@ -49,6 +49,7 @@
49 49
  *  2008-11-18  support for variable parameter module functions (andrei)
50 50
  *  2008-12-03  use lvalues/rvalues for assignments (andrei)
51 51
  *  2008-12-17  added UDP_MTU_TRY_PROTO_T (andrei)
52
+ *  2009-05-04  switched IF_T to rval_expr (andrei)
52 53
  */
53 54
 
54 55
 
... ...
@@ -813,21 +814,14 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
813 813
 				ret=1;
814 814
 				break;
815 815
 		case IF_T:
816
-				/* if null expr => ignore if? */
817
-				if ((a->val[0].type==EXPR_ST)&&a->val[0].u.data){
818
-					v=eval_expr(h, (struct expr*)a->val[0].u.data, msg);
819
-#if 0
820
-					if (v<0){
821
-						if (v==EXPR_DROP){ /* hack to quit on DROP*/
822
-							ret=0;
823
-							break;
824
-						}else{
825
-							LOG(L_WARN,"WARNING: do_action:"
826
-										"error in expression\n");
827
-						}
816
+					rve=(struct rval_expr*)a->val[0].u.data;
817
+					if (unlikely(rval_expr_eval_int(h, msg, &v, rve) != 0)){
818
+						ERR("if expression evaluation failed (%d,%d-%d,%d)\n",
819
+								rve->fpos.s_line, rve->fpos.s_col,
820
+								rve->fpos.e_line, rve->fpos.e_col);
821
+						v=0; /* false */
828 822
 					}
829
-#endif
830
-					if (h->run_flags & EXIT_R_F){
823
+					if (unlikely(h->run_flags & EXIT_R_F)){
831 824
 						ret=0;
832 825
 						break;
833 826
 					}
... ...
@@ -843,7 +837,6 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
843 843
 							ret=run_actions(h,
844 844
 										(struct action*)a->val[2].u.data, msg);
845 845
 					}
846
-				}
847 846
 			break;
848 847
 		case MODULE_T:
849 848
 			if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && 
... ...
@@ -95,6 +95,7 @@
95 95
  *             NUMBER is now always positive; cleanup (andrei)
96 96
  * 2009-01-26  case/switch() support (andrei)
97 97
  * 2009-03-10  added SET_USERPHONE action (Miklos)
98
+ * 2009-05-04  switched if to rval_expr (andrei)
98 99
 */
99 100
 
100 101
 %{
... ...
@@ -212,6 +213,8 @@ static struct rval_expr* mk_rve_rval(enum rval_type, void* v);
212 212
 static struct rval_expr* mk_rve1(enum rval_expr_op op, struct rval_expr* rve1);
213 213
 static struct rval_expr* mk_rve2(enum rval_expr_op op, struct rval_expr* rve1,
214 214
 									struct rval_expr* rve2);
215
+static int rval_expr_int_check(struct rval_expr *rve);
216
+static int warn_ct_rve(struct rval_expr *rve, char* name);
215 217
 static struct socket_id* mk_listen_id(char*, int, int);
216 218
 static struct name_lst* mk_name_lst(char* name, int flags);
217 219
 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);
520 520
 
521 521
 
522 522
 /*non-terminals */
523
-%type <expr> exp exp_elem
523
+/*%type <expr> exp */
524
+%type <expr> exp_elem
524 525
 %type <intval> intno eint_op eint_op_onsend
525 526
 %type <intval> eip_op eip_op_onsend
526 527
 %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 {
1566 1566
 	| ROUTE_SEND error { yyerror("invalid onsend_route statement"); }
1567 1567
 	;
1568 1568
 
1569
-exp:	rval_expr
1569
+/*exp:	rval_expr
1570 1570
 		{
1571 1571
 			if ($1==0){
1572 1572
 				yyerror("invalid expression");
... ...
@@ -1581,6 +1585,7 @@ exp:	rval_expr
1581 1581
 				$$=mk_elem(NO_OP, RVEXP_O, $1, 0, 0);
1582 1582
 		}
1583 1583
 	;
1584
+*/
1584 1585
 
1585 1586
 /* exp elem operators */
1586 1587
 equalop:
... ...
@@ -1852,8 +1857,18 @@ action:
1852 1852
 	| fcmd error { $$=0; yyerror("bad command: missing ';'?"); }
1853 1853
 	;
1854 1854
 if_cmd:
1855
-	IF exp stm		{ $$=mk_action( IF_T, 3, EXPR_ST, $2, ACTIONS_ST, $3, NOSUBTYPE, 0); }
1856
-	| IF exp stm ELSE stm	{ $$=mk_action( IF_T, 3, EXPR_ST, $2, ACTIONS_ST, $3, ACTIONS_ST, $5); }
1855
+	IF rval_expr stm	{
1856
+		if (rval_expr_int_check($2)==0){
1857
+			warn_ct_rve($2, "if");
1858
+		}
1859
+		$$=mk_action( IF_T, 3, RVE_ST, $2, ACTIONS_ST, $3, NOSUBTYPE, 0);
1860
+	}
1861
+	| IF rval_expr stm ELSE stm	{ 
1862
+		if (rval_expr_int_check($2)==0){
1863
+			warn_ct_rve($2, "if");
1864
+		}
1865
+		$$=mk_action( IF_T, 3, RVE_ST, $2, ACTIONS_ST, $3, ACTIONS_ST, $5); 
1866
+	}
1857 1867
 	;
1858 1868
 
1859 1869
 ct_rval: rval_expr {
... ...
@@ -2930,6 +2945,48 @@ static struct rval_expr* mk_rve2(enum rval_expr_op op, struct rval_expr* rve1,
2930 2930
 }
2931 2931
 
2932 2932
 
2933
+/** check if the expression is an int.
2934
+ * if the expression does not evaluate to an int return -1 and
2935
+ * log an error.
2936
+ * @return 0 on success, -1 on error */
2937
+static int rval_expr_int_check(struct rval_expr *rve)
2938
+{
2939
+	struct rval_expr* bad_rve;
2940
+	enum rval_type type, bad_t, exp_t;
2941
+	
2942
+	if (rve==0){
2943
+		yyerror("invalid expression");
2944
+		return -1;
2945
+	}else if (!rve_check_type(&type, rve, &bad_rve, &bad_t ,&exp_t)){
2946
+		if (bad_rve)
2947
+			yyerror_at(&rve->fpos, "bad expression: type mismatch:"
2948
+						" %s instead of %s at (%d,%d)",
2949
+						rval_type_name(bad_t), rval_type_name(exp_t),
2950
+						bad_rve->fpos.s_line, bad_rve->fpos.s_col);
2951
+		else
2952
+			yyerror("BUG: unexpected null \"bad\" expression\n");
2953
+		return -1;
2954
+	}else if (type!=RV_INT && type!=RV_NONE){
2955
+		yyerror_at(&rve->fpos, "invalid expression type, int expected\n");
2956
+		return -1;
2957
+	}
2958
+	return 0;
2959
+}
2960
+
2961
+
2962
+/** warn if the expression is constant.
2963
+ * @return 0 on success (no warning), 1 when warning */
2964
+static int warn_ct_rve(struct rval_expr *rve, char* name)
2965
+{
2966
+	if (rve && rve_is_constant(rve)){
2967
+		warn_at(&rve->fpos, "constant value in %s%s",
2968
+				name?name:"expression", name?"(...)":"");
2969
+		return 1;
2970
+	}
2971
+	return 0;
2972
+}
2973
+
2974
+
2933 2975
 static struct name_lst* mk_name_lst(char* host, int flags)
2934 2976
 {
2935 2977
 	struct name_lst* l;
... ...
@@ -49,6 +49,7 @@
49 49
  *  2008-04-23  errors are treated as false during expression evaluation
50 50
  *  		unless the operator is DIFF_OP (Miklos)
51 51
  *  2008-12-03  fixups for rvalues in assignments (andrei)
52
+ *  2009-05-04  switched IF_T to rval_expr (andrei)
52 53
  */
53 54
 
54 55
 
... ...
@@ -674,24 +675,50 @@ int fix_actions(struct action* a)
674 674
 					}
675 675
 					break;
676 676
 			case IF_T:
677
-				if (t->val[0].type!=EXPR_ST){
677
+				if (t->val[0].type!=RVE_ST){
678 678
 					LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
679
-								"%d for if (should be expr)\n",
679
+								"%d for if (should be rval expr)\n",
680 680
 								t->val[0].type);
681 681
 					return E_BUG;
682
-				}else if( (t->val[1].type!=ACTIONS_ST)&&(t->val[1].type!=NOSUBTYPE) ){
682
+				}else if( (t->val[1].type!=ACTIONS_ST) &&
683
+							(t->val[1].type!=NOSUBTYPE) ){
683 684
 					LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
684 685
 								"%d for if() {...} (should be action)\n",
685 686
 								t->val[1].type);
686 687
 					return E_BUG;
687
-				}else if( (t->val[2].type!=ACTIONS_ST)&&(t->val[2].type!=NOSUBTYPE) ){
688
+				}else if( (t->val[2].type!=ACTIONS_ST) &&
689
+							(t->val[2].type!=NOSUBTYPE) ){
688 690
 					LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
689 691
 								"%d for if() {} else{...}(should be action)\n",
690 692
 								t->val[2].type);
691 693
 					return E_BUG;
692 694
 				}
693
-				if (t->val[0].u.data){
694
-					if ((ret=fix_expr((struct expr*)t->val[0].u.data))<0)
695
+				rve=(struct rval_expr*)t->val[0].u.data;
696
+				if (rve){
697
+					err_rve=0;
698
+					if (!rve_check_type(&rve_type, rve, &err_rve,
699
+											&err_type, &expected_type)){
700
+						if (err_rve)
701
+							LOG(L_ERR, "fix_actions: invalid expression "
702
+									"(%d,%d): subexpression (%d,%d) has type"
703
+									" %s,  but %s is expected\n",
704
+									rve->fpos.s_line, rve->fpos.s_col,
705
+									err_rve->fpos.s_line, err_rve->fpos.s_col,
706
+									rval_type_name(err_type),
707
+									rval_type_name(expected_type) );
708
+						else
709
+							LOG(L_ERR, "fix_actions: invalid expression "
710
+									"(%d,%d): type mismatch?",
711
+									rve->fpos.s_line, rve->fpos.s_col);
712
+						return E_UNSPEC;
713
+					}
714
+					if (rve_type!=RV_INT && rve_type!=RV_NONE){
715
+						LOG(L_ERR, "fix_actions: invalid expression (%d,%d):"
716
+								" bad type, integer expected\n",
717
+								rve->fpos.s_line, rve->fpos.s_col);
718
+						return E_UNSPEC;
719
+					}
720
+					if ((ret=fix_rval_expr((void**)&rve))<0)
695 721
 						return ret;
696 722
 				}
697 723
 				if ( (t->val[1].type==ACTIONS_ST)&&(t->val[1].u.data) ){
... ...
@@ -699,7 +726,8 @@ int fix_actions(struct action* a)
699 699
 						return ret;
700 700
 				}
701 701
 				if ( (t->val[2].type==ACTIONS_ST)&&(t->val[2].u.data) ){
702
-						if ((ret=fix_actions((struct action*)t->val[2].u.data))<0)
702
+						if ((ret=fix_actions((struct action*)t->val[2].u.data))
703
+								<0)
703 704
 						return ret;
704 705
 				}
705 706
 				break;