]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add debug functions for parse rules
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sun, 5 Dec 2021 05:21:41 +0000 (00:21 -0500)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sun, 5 Dec 2021 05:25:38 +0000 (00:25 -0500)
Fix quicksort

src/lib/util/misc.c
src/lib/util/sbuff.c
src/lib/util/sbuff.h
src/tests/unit/condition/xlat.txt [new file with mode: 0644]

index 8de3f3f05f7298032761bc83b3a3938a591cc833..5d6821ecfcaa9a1e79b5921ce8bd346ed38cc4e9 100644 (file)
@@ -598,34 +598,34 @@ int8_t fr_pointer_cmp(void const *a, void const *b)
  *
  * @param to_sort array of pointers to sort.
  * @param start the lowest index (usually 0).
- * @param len the length of the array.
+ * @param end the length of the array.
  * @param cmp the comparison function to use to sort the array elements.
  */
-void fr_quick_sort(void const *to_sort[], int start, int len, fr_cmp_t cmp)
+void fr_quick_sort(void const *to_sort[], int start, int end, fr_cmp_t cmp)
 {
-       int i = start;
-       int j = len;
+       int             i, pi;
+       void const      *pivot;
 
-       void const *pivot  = to_sort[(i + j) / 2];
+       if (start >= end) return;
 
-       while (i < j) {
-               void const *tmp;
-
-               do ++i; while ((i < len) && (cmp(to_sort[i], pivot) < 0));
-               do --j; while ((i > start) && (cmp(to_sort[j], pivot) > 0));
-
-               if (i <= j) {
-                       tmp = to_sort[i];
-                       to_sort[i] = to_sort[j];
-                       to_sort[j] = tmp;
+#define SWAP(_a, _b) \
+       do { \
+               void const *_tmp = to_sort[_a]; \
+               to_sort[_a] = to_sort[_b]; \
+               to_sort[_b] = _tmp; \
+       } while (0)
 
-                       i++;
-                       j--;
+       pivot = to_sort[end];
+       for (pi = start, i = start; i < end; i++) {
+               if (cmp(to_sort[i], pivot) < 0) {
+                       SWAP(i , pi);
+                       pi++;
                }
        }
+       SWAP(end, pi);
 
-       if (start < j) fr_quick_sort(to_sort, start, j, cmp);
-       if (i < len) fr_quick_sort(to_sort, i, len, cmp);
+       fr_quick_sort(to_sort, start, pi - 1, cmp);
+       fr_quick_sort(to_sort, pi + 1, end, cmp);
 }
 
 #ifdef TALLOC_DEBUG
index 78e1c1c22e7fabd2537b01bb7e9a1e7849d76ce8..1602b640b93114572b4135523209e415831a7bae 100644 (file)
@@ -590,7 +590,7 @@ fr_sbuff_term_t *fr_sbuff_terminals_amerge(TALLOC_CTX *ctx, fr_sbuff_term_t cons
        for (j = 0; j < b->len; i++, j++) tmp[i] = &b->elem[j];
 
        if (likely(i > 1)) {
-               fr_quick_sort((void const **)tmp, 0, i, terminal_cmp);
+               fr_quick_sort((void const **)tmp, 0, i - 1, terminal_cmp);
 
                for (j = 0; j < (i - 1); j++) {
                        /*
@@ -2037,3 +2037,99 @@ bool fr_sbuff_is_terminal(fr_sbuff_t *in, fr_sbuff_term_t const *tt)
 
        return fr_sbuff_terminal_search(in, in->p, idx, tt, needle_len);
 }
+
+/** Print a char in a friendly format
+ *
+ */
+static char const *sbuff_print_char(char c)
+{
+       static bool const unprintables[UINT8_MAX + 1] = {
+               SBUFF_CHAR_UNPRINTABLES_LOW,
+               SBUFF_CHAR_UNPRINTABLES_EXTENDED
+       };
+
+       static _Thread_local char str[10][5];
+       static _Thread_local char **p;
+
+       switch (c) {
+       case '\a':
+               return "\a";
+
+       case '\b':
+               return "\b";
+
+       case '\n':
+               return "\n";
+
+       case '\r':
+               return "\r";
+
+       case '\t':
+               return "\t";
+
+       case '\f':
+               return "\f";
+
+       case '\v':
+               return "\v";
+
+       default:
+               if (!p || (p++ >= ((char **)str + (NUM_ELEMENTS(str) - 1)))) p = (char **)str;
+
+               if (unprintables[(uint8_t)c]) {
+                       snprintf(*p, sizeof(*str), "\\x%x", c);
+                       return *p;
+               }
+
+               *p[0] = c;
+               *p[1] = '\0';
+               return *p;
+       }
+}
+
+void fr_sbuff_unescape_debug(fr_sbuff_unescape_rules_t const *escapes)
+{
+       uint8_t i;
+
+       FR_FAULT_LOG("Escape rules %s (%p)", escapes->name, escapes);
+       FR_FAULT_LOG("chr     : %c", escapes->chr ? escapes->chr : ' ');
+       FR_FAULT_LOG("do_hex  : %s", escapes->do_hex ? "yes" : "no");
+       FR_FAULT_LOG("do_oct  : %s", escapes->do_oct ? "yes" : "no");
+
+       FR_FAULT_LOG("substitutions:");
+       for (i = 0; i < UINT8_MAX; i++) {
+               if (escapes->subs[i]) FR_FAULT_LOG("\t%s -> %s",
+                                                  sbuff_print_char((char)i),
+                                                  sbuff_print_char((char)escapes->subs[i]));
+       }
+       FR_FAULT_LOG("skipes:");
+       for (i = 0; i < UINT8_MAX; i++) {
+               if (escapes->skip[i]) FR_FAULT_LOG("\t%s", sbuff_print_char((char)i));
+       }
+}
+
+void fr_sbuff_terminal_debug(fr_sbuff_term_t const *tt)
+{
+       size_t i;
+
+       FR_FAULT_LOG("Terminal count %zu", tt->len);
+
+       for (i = 0; i < tt->len; i++) FR_FAULT_LOG("\t\"%s\" (%zu)", tt->elem[i].str, tt->elem[i].len);
+}
+
+void fr_sbuff_parse_rules_debug(fr_sbuff_parse_rules_t const *p_rules)
+{
+       FR_FAULT_LOG("Parse rules %p", p_rules);
+
+       if (p_rules->escapes) {
+               fr_sbuff_unescape_debug(p_rules->escapes);
+       } else {
+               FR_FAULT_LOG("No unescapes");
+       }
+
+       if (p_rules->terminals) {
+               fr_sbuff_terminal_debug(p_rules->terminals);
+       } else {
+               FR_FAULT_LOG("No terminals");
+       }
+}
index dee5033902e3fabe3d8ca142e27dbd1c1b8c196b..afe979e105220c91a7a5e9425beb812aab71a091 100644 (file)
@@ -1700,6 +1700,12 @@ static inline bool _fr_sbuff_is_hex(fr_sbuff_t *sbuff, char const *p)
 
 /** @} */
 
+void   fr_sbuff_unescape_debug(fr_sbuff_unescape_rules_t const *escapes);
+
+void   fr_sbuff_terminal_debug(fr_sbuff_term_t const *tt);
+
+void   fr_sbuff_parse_rules_debug(fr_sbuff_parse_rules_t const *p_rules);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/tests/unit/condition/xlat.txt b/src/tests/unit/condition/xlat.txt
new file mode 100644 (file)
index 0000000..deab84c
--- /dev/null
@@ -0,0 +1,10 @@
+proto-dictionary radius
+
+condition %(integer:0)
+match %(integer:0)
+
+condition (%(integer:0))
+match %(integer:0)
+
+count
+match 5