@@ -217,11 +217,11 @@ int run_top_route(struct action* a, struct sip_msg* msg)
217
217
/* execute assignment operation */
218
218
int do_assign (struct sip_msg * msg , struct action * a )
219
219
{
220
+ str st ;
220
221
int ret ;
221
- pv_value_t val ;
222
+ pv_value_t lval , val ;
222
223
pv_spec_p dspec ;
223
224
224
- ret = -1 ;
225
225
dspec = (pv_spec_p )a -> elem [0 ].u .data ;
226
226
if (!pv_is_w (dspec ))
227
227
{
@@ -241,52 +241,142 @@ int do_assign(struct sip_msg* msg, struct action* a)
241
241
}
242
242
}
243
243
244
- switch ((unsigned char )a -> type ){
245
- case EQ_T :
246
- case COLONEQ_T :
247
- case PLUSEQ_T :
248
- case MINUSEQ_T :
249
- case DIVEQ_T :
250
- case MULTEQ_T :
251
- case MODULOEQ_T :
252
- case BANDEQ_T :
253
- case BOREQ_T :
254
- case BXOREQ_T :
255
- script_trace ("assign" ,
256
- (unsigned char )a -> type == EQ_T ? "equal" :
257
- (unsigned char )a -> type == COLONEQ_T ? "colon-eq" :
258
- (unsigned char )a -> type == PLUSEQ_T ? "plus-eq" :
259
- (unsigned char )a -> type == MINUSEQ_T ? "minus-eq" :
260
- (unsigned char )a -> type == DIVEQ_T ? "div-eq" :
261
- (unsigned char )a -> type == MULTEQ_T ? "mult-eq" :
262
- (unsigned char )a -> type == MODULOEQ_T ? "modulo-eq" :
263
- (unsigned char )a -> type == BANDEQ_T ? "b-and-eq" :
264
- (unsigned char )a -> type == BOREQ_T ? "b-or-eq" :"b-xor-eq" ,
265
- msg , a -> file , a -> line );
266
-
267
- if (a -> elem [1 ].type == NULLV_ST || (val .flags & PV_VAL_NULL ))
268
- {
269
- if (pv_set_value (msg , dspec , (int )a -> type , 0 )< 0 )
270
- {
271
- LM_ERR ("setting PV failed\n" );
244
+ switch (a -> type ) {
245
+ case EQ_T :
246
+ case COLONEQ_T :
247
+ break ;
248
+ case PLUSEQ_T :
249
+ case MINUSEQ_T :
250
+ case DIVEQ_T :
251
+ case MULTEQ_T :
252
+ case MODULOEQ_T :
253
+ case BANDEQ_T :
254
+ case BOREQ_T :
255
+ case BXOREQ_T :
256
+ if (pv_get_spec_value (msg , dspec , & lval ) != 0 ) {
257
+ LM_ERR ("failed to get left-hand side value\n" );
258
+ goto error ;
259
+ }
260
+
261
+ if (lval .flags & PV_VAL_NULL || val .flags & PV_VAL_NULL ) {
262
+ LM_ERR ("NULL value(s) in complex assignment expressions "
263
+ "(+=, -=, etc.)\n" );
264
+ goto error ;
265
+ }
266
+
267
+ /* both include STR versions and neither is primarily an INT */
268
+ if ((lval .flags & PV_VAL_STR ) && (val .flags & PV_VAL_STR ) &&
269
+ !(lval .flags & PV_TYPE_INT ) && !(val .flags & PV_TYPE_INT )) {
270
+ val .ri = 0 ;
271
+
272
+ if (a -> type != PLUSEQ_T )
273
+ goto bad_operands ;
274
+
275
+ if (!(val .flags & PV_VAL_PKG )) {
276
+ st = val .rs ;
277
+ val .rs .s = pkg_malloc (val .rs .len + lval .rs .len + 1 );
278
+ if (!val .rs .s ) {
279
+ val .rs .s = st .s ;
280
+ LM_ERR ("oom 1\n" );
272
281
goto error ;
273
282
}
283
+
284
+ memcpy (val .rs .s , lval .rs .s , lval .rs .len );
285
+ memcpy (val .rs .s + lval .rs .len , st .s , st .len );
286
+ val .rs .len += lval .rs .len ;
287
+ val .rs .s [val .rs .len ] = '\0' ;
288
+ val .flags |= PV_VAL_PKG ;
289
+
290
+ if (val .flags & PV_VAL_SHM ) {
291
+ val .flags &= ~PV_VAL_SHM ;
292
+ shm_free (st .s );
293
+ }
274
294
} else {
275
- if ( pv_set_value ( msg , dspec , ( int ) a -> type , & val ) < 0 )
276
- {
277
- LM_ERR ("setting PV failed \n" );
295
+ st . len = val . rs . len ;
296
+ if ( pkg_str_extend ( & val . rs , val . rs . len + lval . rs . len + 1 ) != 0 ) {
297
+ LM_ERR ("oom 2 \n" );
278
298
goto error ;
279
299
}
300
+ val .rs .len -- ;
301
+ memmove (val .rs .s + lval .rs .len , val .rs .s , st .len );
302
+ memcpy (val .rs .s , lval .rs .s , lval .rs .len );
303
+ val .rs .s [val .rs .len ] = '\0' ;
280
304
}
281
- ret = 1 ;
305
+ } else if ((lval .flags & PV_VAL_INT ) && (val .flags & PV_VAL_INT )) {
306
+ if (val .flags & PV_VAL_STR )
307
+ val .flags &= ~PV_VAL_STR ;
308
+ switch (a -> type ) {
309
+ case PLUSEQ_T :
310
+ val .ri = lval .ri + val .ri ;
311
+ break ;
312
+ case MINUSEQ_T :
313
+ val .ri = lval .ri - val .ri ;
314
+ break ;
315
+ case DIVEQ_T :
316
+ val .ri = lval .ri / val .ri ;
317
+ break ;
318
+ case MULTEQ_T :
319
+ val .ri = lval .ri * val .ri ;
320
+ break ;
321
+ case MODULOEQ_T :
322
+ val .ri = lval .ri % val .ri ;
323
+ break ;
324
+ case BANDEQ_T :
325
+ val .ri = lval .ri & val .ri ;
326
+ break ;
327
+ case BOREQ_T :
328
+ val .ri = lval .ri | val .ri ;
329
+ break ;
330
+ case BXOREQ_T :
331
+ val .ri = lval .ri ^ val .ri ;
332
+ break ;
333
+ }
334
+ } else {
335
+ goto bad_operands ;
336
+ }
282
337
break ;
283
- default :
284
- LM_ALERT ("BUG -> unknown op type %d\n" , a -> type );
338
+ default :
339
+ LM_ALERT ("BUG -> unknown op type %d\n" , a -> type );
340
+ goto error ;
341
+ }
342
+
343
+ script_trace ("assign" ,
344
+ (unsigned char )a -> type == EQ_T ? "equal" :
345
+ (unsigned char )a -> type == COLONEQ_T ? "colon-eq" :
346
+ (unsigned char )a -> type == PLUSEQ_T ? "plus-eq" :
347
+ (unsigned char )a -> type == MINUSEQ_T ? "minus-eq" :
348
+ (unsigned char )a -> type == DIVEQ_T ? "div-eq" :
349
+ (unsigned char )a -> type == MULTEQ_T ? "mult-eq" :
350
+ (unsigned char )a -> type == MODULOEQ_T ? "modulo-eq" :
351
+ (unsigned char )a -> type == BANDEQ_T ? "b-and-eq" :
352
+ (unsigned char )a -> type == BOREQ_T ? "b-or-eq" :"b-xor-eq" ,
353
+ msg , a -> file , a -> line );
354
+
355
+ if (a -> elem [1 ].type == NULLV_ST || (val .flags & PV_VAL_NULL ))
356
+ {
357
+ if (pv_set_value (msg , dspec , (int )a -> type , 0 )< 0 )
358
+ {
359
+ LM_ERR ("setting PV failed\n" );
285
360
goto error ;
361
+ }
362
+ } else {
363
+ if (pv_set_value (msg , dspec , (int )a -> type , & val )< 0 )
364
+ {
365
+ LM_ERR ("setting PV failed\n" );
366
+ goto error ;
367
+ }
286
368
}
287
369
288
370
pv_value_destroy (& val );
289
- return ret ;
371
+ return 1 ;
372
+
373
+ bad_operands :
374
+ LM_ERR ("unsupported operand type(s) for %s: %s and %s\n" ,
375
+ assignop_str (a -> type ),
376
+ lval .flags & PV_VAL_STR ? "string" : "int" ,
377
+ val .flags & PV_VAL_STR ? "string" : "int" );
378
+ pv_value_destroy (& val );
379
+ return -1 ;
290
380
291
381
error :
292
382
LM_ERR ("error at %s:%d\n" , a -> file , a -> line );
0 commit comments