@@ -6848,6 +6848,97 @@ int fr_value_box_list_escape_in_place(fr_value_box_list_t *list, fr_value_box_es
68486848 return ret ;
68496849}
68506850
6851+ typedef struct {
6852+ TALLOC_CTX * ctx ;
6853+ fr_sbuff_escape_rules_t const * erules ;
6854+ } fr_value_box_escape_rules_ctx_t ;
6855+
6856+ static int _value_box_escape_rules (fr_value_box_t * vb , void * uctx )
6857+ {
6858+ fr_value_box_escape_rules_ctx_t * ctx = uctx ;
6859+
6860+ if (fr_type_is_leaf (vb -> type )) {
6861+ if (fr_value_box_escape_in_place_erules (ctx -> ctx , vb , ctx -> erules ) < 0 ) return -1 ;
6862+
6863+ return 1 ; /* safe_for has been updated */
6864+ }
6865+
6866+ return fr_value_box_escape_in_place (vb ,
6867+ & (fr_value_box_escape_t ) {
6868+ .func = _value_box_escape_rules ,
6869+ .safe_for = ctx -> erules ,
6870+ .always_escape = true,
6871+ },
6872+ & (fr_value_box_escape_rules_ctx_t ) {
6873+ .ctx = vb ,
6874+ .erules = ctx -> erules ,
6875+ }
6876+ );
6877+ }
6878+
6879+ /** Escape a value-box in place using sbuff escaping rules, and mark it safe-for.
6880+ *
6881+ * If the input type isn't a string, then it is converted to a string.
6882+ *
6883+ * The output type is always #FR_TYPE_STRING
6884+ *
6885+ * @param[in] ctx to allocate any new buffers in.
6886+ * @param[in] vb which will be escaped
6887+ * @param[in] erules escape rules
6888+ * @return
6889+ * - <0 for error, generally OOM
6890+ * - 0 for success
6891+ */
6892+ int fr_value_box_escape_in_place_erules (TALLOC_CTX * ctx , fr_value_box_t * vb , fr_sbuff_escape_rules_t const * erules )
6893+ {
6894+ ssize_t slen ;
6895+ fr_sbuff_t * escaped = NULL ;
6896+
6897+ FR_SBUFF_TALLOC_THREAD_LOCAL (& escaped , 256 , 4096 );
6898+
6899+ /*
6900+ * Structural types are much more complicated. :(
6901+ */
6902+ if (!fr_type_is_leaf (vb -> type )) {
6903+ int rcode ;
6904+
6905+ rcode = fr_value_box_escape_in_place (vb ,
6906+ & (fr_value_box_escape_t ) {
6907+ .func = _value_box_escape_rules ,
6908+ .safe_for = erules ,
6909+ .always_escape = true,
6910+ },
6911+ & (fr_value_box_escape_rules_ctx_t ) {
6912+ .ctx = ctx ,
6913+ .erules = erules ,
6914+ }
6915+ );
6916+ if (rcode < 0 ) return rcode ;
6917+
6918+ rcode = fr_value_box_list_concat_as_string (NULL , escaped , & vb -> vb_group , NULL , 0 , NULL ,
6919+ FR_VALUE_BOX_LIST_FREE , erules , true);
6920+ fr_assert (fr_value_box_list_num_elements (& vb -> vb_group ) == 0 );
6921+
6922+ goto set_value ;
6923+ }
6924+
6925+ if (vb -> type != FR_TYPE_STRING ) {
6926+ if (fr_value_box_cast_in_place (ctx , vb , FR_TYPE_STRING , NULL ) < 0 ) return -1 ;
6927+ } else {
6928+ if (fr_value_box_is_safe_for (vb , erules )) return 0 ;
6929+ }
6930+
6931+ slen = fr_sbuff_in_escape (escaped , vb -> vb_strvalue , vb -> vb_length , erules );
6932+ if (slen < 0 ) return -1 ;
6933+
6934+ set_value :
6935+ if (fr_value_box_bstrndup (ctx , vb , NULL , fr_sbuff_start (escaped ), fr_sbuff_used (escaped ), false) < 0 ) return -1 ;
6936+
6937+ fr_value_box_mark_safe_for (vb , erules );
6938+
6939+ return 0 ;
6940+ }
6941+
68516942/** Removes a single layer of nesting, moving all children into the parent list
68526943 *
68536944 * @param[in] ctx to reparent children in if steal is true.
0 commit comments