Browse code

core: avp & pvars assignment fixes & changes

- fix: delete avps after finding their new value and not before
(fixes $v=$v or $v=$avp(v) deleting $v's value)

- when assigning something undefined (like a non-existing avp),
delete the lvalue.
E.g.: $v=$foo and $ foo undefined => delete/undefine $v
An expr is undefined only if it consists only on an undefined
avp or pvar. If it contains more elements it's always defined
(even if all the elements are undefined).
E.g: $foo and $bar are undefined => defined $foo == 0, defined
$bar == 0, but defined ($foo+$bar) == 1.
An avp is undefined if it doesn't exist or there is some error
accessing it.
A pvar is undefined if it's PV_VAL_NULL or there is an error
getting it's value.

Andrei Pelinescu-Onciul authored on 24/04/2009 19:40:26
Showing 1 changed files
... ...
@@ -23,6 +23,10 @@
23 23
  * History:
24 24
  * --------
25 25
  *  2008-11-30  initial version (andrei)
26
+ *  2009-04-24  delete avps after finding their new value and not before
27
+ *               (fixed $avp=$avp)
28
+ *              when assigning something undefined (e.g. non-existing avp),
29
+ *              delete the lvalue (similar to perl)  (andrei)
26 30
  */
27 31
 
28 32
 #include "lvalue.h"
... ...
@@ -53,19 +57,37 @@ inline static int lval_avp_assign(struct run_act_ctx* h, struct sip_msg* msg,
53 53
 	unsigned short flags;
54 54
 	struct search_state st;
55 55
 	int ret, v, destroy_pval;
56
+	int avp_add;
57
+
58
+#if 0
59
+	#define AVP_ASSIGN_NOVAL() \
60
+		/* unknown value => reset the avp in function of its type */ \
61
+		flags=avp->type; \
62
+		if (flags & AVP_VAL_STR){ \
63
+			value.s.s=""; \
64
+			value.s.len=0; \
65
+		}else{ \
66
+			value.n=0; \
67
+		}
68
+#endif
69
+	#define AVP_ASSIGN_NOVAL() \
70
+		/* no value => delete avp */ \
71
+		avp_add=0
56 72
 	
57 73
 	destroy_pval=0;
58 74
 	flags = 0;
59 75
 	avp=&lv->lv.avps;
60 76
 	ret=0;
61
-	/* If the left attr was specified without indexing brackets delete
62
-	 * existing AVPs before adding new ones */
63
-	if ((avp->type & AVP_INDEX_ALL) != AVP_INDEX_ALL)
64
-		delete_avp(avp->type, avp->name);
77
+	avp_add=1;
78
+	
65 79
 	switch(rv->type){
66 80
 		case RV_NONE:
67 81
 			BUG("non-intialized rval / rval expr \n");
68
-			goto error;
82
+			/* unknown value => reset the avp in function of its type */
83
+			flags=avp->type;
84
+			AVP_ASSIGN_NOVAL();
85
+			ret=-1;
86
+			break;
69 87
 		case RV_INT:
70 88
 			value.n=rv->v.l;
71 89
 			flags=avp->type & ~AVP_VAL_STR;
... ...
@@ -96,22 +118,22 @@ inline static int lval_avp_assign(struct run_act_ctx* h, struct sip_msg* msg,
96 96
 			ret=value.n;
97 97
 			break;
98 98
 		case RV_SEL:
99
+			flags=avp->type|AVP_VAL_STR;
99 100
 			v=run_select(&value.s, &rv->v.sel, msg);
100 101
 			if (unlikely(v!=0)){
102
+				value.s.s="";
103
+				value.s.len=0;
101 104
 				if (v<0){
102 105
 					ret=-1;
103
-					goto error;
104
-				}else { /* v>0 */
105
-					value.s.s="";
106
-					value.s.len=0;
107
-				}
106
+					break;
107
+				} /* v>0 */
108 108
 			}
109
-			flags=avp->type|AVP_VAL_STR;
110 109
 			ret=(value.s.len>0);
111 110
 			break;
112 111
 		case RV_AVP:
113 112
 			avp_mark=0;
114 113
 			if (unlikely((rv->v.avps.type & AVP_INDEX_ALL) == AVP_INDEX_ALL)){
114
+				/* special case: add the value to the avp */
115 115
 				r_avp = search_first_avp(rv->v.avps.type, rv->v.avps.name,
116 116
 											&value, &st);
117 117
 				while(r_avp){
... ...
@@ -136,6 +158,7 @@ inline static int lval_avp_assign(struct run_act_ctx* h, struct sip_msg* msg,
136 136
 				ret=1;
137 137
 				goto end;
138 138
 			}else{
139
+				/* normal case, value is replaced */
139 140
 				r_avp = search_avp_by_index(rv->v.avps.type, rv->v.avps.name,
140 141
 											&value, rv->v.avps.index);
141 142
 				if (likely(r_avp)){
... ...
@@ -146,8 +169,11 @@ inline static int lval_avp_assign(struct run_act_ctx* h, struct sip_msg* msg,
146 146
 									AVP_NAME_RE));
147 147
 					ret=1;
148 148
 				}else{
149
-					ret=-1;
150
-					goto error;
149
+					/* on error, keep the type of the assigned avp, but
150
+					   reset it to an empty value */
151
+					AVP_ASSIGN_NOVAL();
152
+					ret=0;
153
+					break;
151 154
 				}
152 155
 			}
153 156
 			break;
... ...
@@ -165,21 +191,22 @@ inline static int lval_avp_assign(struct run_act_ctx* h, struct sip_msg* msg,
165 165
 					flags=avp->type | AVP_VAL_STR;
166 166
 				}else if (pval.flags==PV_VAL_NONE ||
167 167
 							(pval.flags & (PV_VAL_NULL|PV_VAL_EMPTY))){
168
-					value.s.s="";
169
-					value.s.len=0;
168
+					AVP_ASSIGN_NOVAL();
170 169
 					ret=0;
171
-					flags=avp->type | AVP_VAL_STR;
172 170
 				}
173 171
 			}else{
174 172
 				/* non existing pvar */
175
-				value.s.s="";
176
-				value.s.len=0;
173
+				/* on error, keep the type of the assigned avp, but
174
+				   reset it to an empty value */
175
+				AVP_ASSIGN_NOVAL();
177 176
 				ret=0;
178
-				flags=avp->type | AVP_VAL_STR;
179 177
 			}
180 178
 			break;
181 179
 	}
182
-	if (add_avp(flags & ~AVP_INDEX_ALL, avp->name, value) < 0) {
180
+	/* If the left attr was specified without indexing brackets delete
181
+	 * existing AVPs before adding the new value */
182
+	delete_avp(avp->type, avp->name);
183
+	if (avp_add && (add_avp(flags & ~AVP_INDEX_ALL, avp->name, value) < 0)) {
183 184
 		ERR("failed to assign value to avp\n");
184 185
 		goto error;
185 186
 	}
... ...
@@ -218,6 +245,10 @@ inline static int lval_pvar_assign(struct run_act_ctx* h, struct sip_msg* msg,
218 218
 	int v;
219 219
 	int destroy_pval;
220 220
 	
221
+	#define PVAR_ASSIGN_NOVAL() \
222
+		/* no value found => "undefine" */ \
223
+		pv_get_null(msg, 0, &pval)
224
+	
221 225
 	destroy_pval=0;
222 226
 	pvar=&lv->lv.pvs;
223 227
 	if (unlikely(!pv_is_w(pvar))){
... ...
@@ -229,7 +260,9 @@ inline static int lval_pvar_assign(struct run_act_ctx* h, struct sip_msg* msg,
229 229
 	switch(rv->type){
230 230
 		case RV_NONE:
231 231
 			BUG("non-intialized rval / rval expr \n");
232
-			goto error;
232
+			PVAR_ASSIGN_NOVAL();
233
+			ret=-1;
234
+			break;
233 235
 		case RV_INT:
234 236
 			pval.flags=PV_TYPE_INT|PV_VAL_INT;
235 237
 			pval.ri=rv->v.l;
... ...
@@ -263,12 +296,12 @@ inline static int lval_pvar_assign(struct run_act_ctx* h, struct sip_msg* msg,
263 263
 			pval.flags=PV_VAL_STR;
264 264
 			v=run_select(&pval.rs, &rv->v.sel, msg);
265 265
 			if (unlikely(v!=0)){
266
+				pval.flags|=PV_VAL_EMPTY;
267
+				pval.rs.s="";
268
+				pval.rs.len=0;
266 269
 				if (v<0){
267 270
 					ret=-1;
268
-					goto error;
269
-				}else { /* v>0 */
270
-					pval.rs.s="";
271
-					pval.rs.len=0;
271
+					break;
272 272
 				}
273 273
 			}
274 274
 			ret=(pval.rs.len)>0;
... ...
@@ -287,8 +320,9 @@ inline static int lval_pvar_assign(struct run_act_ctx* h, struct sip_msg* msg,
287 287
 						ret=!(!pval.ri);
288 288
 					}
289 289
 				}else{
290
-					ret=-1;
291
-					goto error;
290
+					PVAR_ASSIGN_NOVAL();
291
+					ret=0; /* avp not defined (valid case) */
292
+					break;
292 293
 				}
293 294
 			break;
294 295
 		case RV_PVAR:
... ...
@@ -299,14 +333,13 @@ inline static int lval_pvar_assign(struct run_act_ctx* h, struct sip_msg* msg,
299 299
 				}else if (pval.flags & PV_VAL_STR){
300 300
 					ret=(pval.rs.len>0);
301 301
 				}else{
302
-					ERR("no value in pvar assignment rval\n");
303
-					ret=-1;
304
-					goto error;
302
+					/* no value / not defined (e.g. avp) -> keep the flags */
303
+					ret=0;
305 304
 				}
306 305
 			}else{
307 306
 				ERR("non existing right pvar\n");
307
+				PVAR_ASSIGN_NOVAL();
308 308
 				ret=-1;
309
-				goto error;
310 309
 			}
311 310
 			break;
312 311
 	}