@@ -366,24 +366,39 @@ static ssize_t decode_option(TALLOC_CTX *ctx, fr_pair_list_t *out,
366366 slen = fr_pair_array_from_network (ctx , out , da , data + 4 , len , decode_ctx , decode_value );
367367
368368 } else if (da -> type == FR_TYPE_VSA ) {
369- bool append = false;
370369 fr_pair_t * vp ;
371370
372371 vp = fr_pair_find_by_da (out , NULL , da );
373372 if (!vp ) {
373+ fr_pair_list_t staging_list ;
374+
374375 vp = fr_pair_afrom_da (ctx , da );
375376 if (!vp ) return PAIR_DECODE_FATAL_ERROR ;
376377 PAIR_ALLOCED (vp );
377378
378- append = true;
379- }
380-
381- slen = decode_vsa (vp , & vp -> vp_group , da , data + 4 , len , decode_ctx );
382- if (append ) {
379+ fr_pair_list_init (& staging_list );
380+ slen = decode_vsa (vp , & staging_list , da , data + 4 , len , decode_ctx );
383381 if (slen < 0 ) {
382+ fr_pair_list_free (& staging_list );
384383 TALLOC_FREE (vp );
385- } else {
386- fr_pair_append (out , vp );
384+ goto raw ;
385+ }
386+ fr_pair_list_append (& vp -> vp_group , & staging_list );
387+ fr_pair_append (out , vp );
388+ } else {
389+ fr_pair_t * tail = fr_pair_list_tail (& vp -> vp_group );
390+
391+ slen = decode_vsa (vp , & vp -> vp_group , da , data + 4 , len , decode_ctx );
392+ if (slen < 0 ) {
393+ /* Remove any new options added to the group */
394+ fr_pair_t * p = tail ? fr_pair_list_next (& vp -> vp_group , tail ) : fr_pair_list_head (& vp -> vp_group );
395+ while (p ) {
396+ fr_pair_t * next = fr_pair_list_next (& vp -> vp_group , p );
397+ fr_pair_remove (& vp -> vp_group , p );
398+ TALLOC_FREE (p );
399+ p = next ;
400+ }
401+ goto raw ;
387402 }
388403 }
389404
0 commit comments