From: Alan T. DeKok Date: Mon, 7 Aug 2023 13:10:21 +0000 (-0400) Subject: add and use fr_pair_list_print() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=80fb5c1ff3e0bf3b748bd21e9424382e3673ec49;p=thirdparty%2Ffreeradius-server.git add and use fr_pair_list_print() so that we can hoist the "nested or not" debug printing into this function. Which also lets this function peek ahead, and print attributes as if they were nested when they really aren't --- diff --git a/src/bin/unit_test_attribute.c b/src/bin/unit_test_attribute.c index c542d295855..58626b7df6f 100644 --- a/src/bin/unit_test_attribute.c +++ b/src/bin/unit_test_attribute.c @@ -1180,8 +1180,6 @@ static size_t command_normalise_attribute(command_result_t *result, command_file { fr_pair_list_t head; ssize_t slen; - char *p, *end; - fr_pair_t *vp; fr_dict_t const *dict = cc->tmpl_rules.attr.dict_def ? cc->tmpl_rules.attr.dict_def : cc->config->dict; fr_pair_list_init(&head); @@ -1190,40 +1188,18 @@ static size_t command_normalise_attribute(command_result_t *result, command_file RETURN_OK_WITH_ERROR(); } - /* - * Set p to be the output buffer - */ - p = data; - end = p + COMMAND_OUTPUT_MAX; - /* * Output may be an error, and we ignore * it if so. */ - if (!fr_pair_list_empty(&head)) { - for (vp = fr_pair_list_head(&head); - vp; - vp = fr_pair_list_next(&head, vp)) { - if ((slen = fr_pair_print(&FR_SBUFF_OUT(p, end), NULL, vp)) < 0) { - oob: - fr_strerror_const("Out of output buffer space for printed pairs"); - RETURN_COMMAND_ERROR(); - } - p += slen; - - if (fr_pair_list_next(&head, vp)) { - slen = strlcpy(p, ", ", end - p); - if (is_truncated((size_t)slen, end - p)) goto oob; - p += slen; - } - } - fr_pair_list_free(&head); - } else { /* zero-length to_decibute */ - *p = '\0'; + slen = fr_pair_list_print(&FR_SBUFF_OUT(data, COMMAND_OUTPUT_MAX), &head); + if (slen <= 0) { + fr_assert(0); + RETURN_OK_WITH_ERROR(); } - RETURN_OK(p - data); + RETURN_OK(slen); } static const fr_token_t token2op[UINT8_MAX + 1] = { @@ -1542,11 +1518,10 @@ static size_t command_decode_pair(command_result_t *result, command_file_ctx_t * { fr_test_point_pair_decode_t *tp = NULL; void *decode_ctx = NULL; - char *p, *end; + char *p; uint8_t *to_dec; uint8_t *to_dec_end; fr_pair_list_t head; - fr_pair_t *vp; ssize_t slen; fr_pair_list_init(&head); @@ -1618,42 +1593,18 @@ static size_t command_decode_pair(command_result_t *result, command_file_ctx_t * fr_strerror_clear(); ASAN_UNPOISON_MEMORY_REGION(to_dec_end, COMMAND_OUTPUT_MAX - slen); - /* - * Set p to be the output buffer - */ - p = data; - end = p + COMMAND_OUTPUT_MAX; - /* * Output may be an error, and we ignore * it if so. */ - - if (!fr_pair_list_empty(&head)) { - for (vp = fr_pair_list_head(&head); - vp; - vp = fr_pair_list_next(&head, vp)) { - if ((slen = fr_pair_print(&FR_SBUFF_OUT(p, end), NULL, vp)) < 0) { - oob: - fr_strerror_const("Out of output buffer space for printed pairs"); - CLEAR_TEST_POINT(cc); - RETURN_COMMAND_ERROR(); - } - p += slen; - - if (fr_pair_list_next(&head, vp)) { - slen = strlcpy(p, ", ", end - p); - if (is_truncated((size_t)slen, end - p)) goto oob; - p += slen; - } - } - fr_pair_list_free(&head); - } else { /* zero-length to_decibute */ - *p = '\0'; + slen = fr_pair_list_print(&FR_SBUFF_OUT(data, COMMAND_OUTPUT_MAX), &head); + if (slen <= 0) { + fr_assert(0); + RETURN_OK_WITH_ERROR(); } CLEAR_TEST_POINT(cc); - RETURN_OK(p - data); + RETURN_OK(slen); } static size_t command_decode_proto(command_result_t *result, command_file_ctx_t *cc, @@ -1665,9 +1616,7 @@ static size_t command_decode_proto(command_result_t *result, command_file_ctx_t uint8_t *to_dec; uint8_t *to_dec_end; fr_pair_list_t head; - fr_pair_t *vp; ssize_t slen; - fr_sbuff_t sbuff = FR_SBUFF_OUT(data, COMMAND_OUTPUT_MAX); p = in; fr_pair_list_init(&head); @@ -1730,28 +1679,17 @@ static size_t command_decode_proto(command_result_t *result, command_file_ctx_t * it if so. */ - if (!fr_pair_list_empty(&head)) { - for (vp = fr_pair_list_head(&head); - vp; - vp = fr_pair_list_next(&head, vp)) { - if ((slen = fr_pair_print(&sbuff, NULL, vp)) < 0) { - oob: - fr_strerror_printf("Out of output buffer space (%zd) for decoded data", slen); - CLEAR_TEST_POINT(cc); - RETURN_COMMAND_ERROR(); - } - - if (fr_pair_list_next(&head, vp)) { - if (fr_sbuff_in_char(&sbuff, ',', ' ') <= 0) goto oob; - } - } - fr_pair_list_free(&head); - } else { /* zero-length to_decibute */ - *data = '\0'; + /* + * Print the pairs. + */ + slen = fr_pair_list_print(&FR_SBUFF_OUT(data, COMMAND_OUTPUT_MAX), &head); + if (slen <= 0) { + fr_assert(0); + RETURN_OK_WITH_ERROR(); } CLEAR_TEST_POINT(cc); - RETURN_OK(fr_sbuff_used(&sbuff)); + RETURN_OK(slen); } /** Parse a dictionary attribute, writing "ok" to the data buffer is everything was ok @@ -2061,9 +1999,8 @@ static size_t command_read_file(command_result_t *result, command_file_ctx_t *cc { ssize_t slen; fr_pair_list_t head; - fr_pair_t *vp; bool done = false; - char *filename, *p, *end; + char *filename; FILE *fp; filename = talloc_asprintf(cc->tmp_ctx, "%s/%s", cc->path, in); @@ -2086,31 +2023,20 @@ static size_t command_read_file(command_result_t *result, command_file_ctx_t *cc /* * Print the pairs. */ - p = data; - end = data + COMMAND_OUTPUT_MAX; - for (vp = fr_pair_list_head(&head); - vp != NULL; - vp = fr_pair_list_next(&head, vp)) { - if ((slen = fr_pair_print(&FR_SBUFF_OUT(p, end), NULL, vp)) <= 0) RETURN_OK_WITH_ERROR(); - p += (size_t)slen; - - if (p >= end) break; - - *(p++) = ','; - *(p++) = ' '; + slen = fr_pair_list_print(&FR_SBUFF_OUT(data, COMMAND_OUTPUT_MAX), &head); + if (slen <= 0) { + fr_assert(0); + RETURN_OK_WITH_ERROR(); } - /* - * Delete the trailing ", ". - */ - if (p > data) p -= 2; - *p = 0; - - if (!done) strlcpy(p, "!DONE", (end - p)); + if (!done) { + strlcpy(data + slen, "!DONE", COMMAND_OUTPUT_MAX - slen); + slen += 5; + } fr_pair_list_free(&head); - RETURN_OK(p - data); + RETURN_OK(slen); } @@ -2583,7 +2509,6 @@ static size_t command_pair(command_result_t *result, command_file_ctx_t *cc, { ssize_t slen; fr_pair_ctx_t ctx; - fr_pair_t *vp; fr_pair_list_t head; char *p, *end; @@ -2610,29 +2535,15 @@ static size_t command_pair(command_result_t *result, command_file_ctx_t *cc, PAIR_LIST_VERIFY(&head); - p = data; - end = data + COMMAND_OUTPUT_MAX; - for (vp = fr_pair_list_head(&head); - vp != NULL; - vp = fr_pair_list_next(&head, vp)) { - if ((slen = fr_pair_print(&FR_SBUFF_OUT(p, end), NULL, vp)) <= 0) RETURN_OK_WITH_ERROR(); - p += (size_t)slen; - - if (p >= end) break; - - *(p++) = ','; - *(p++) = ' '; + slen = fr_pair_list_print(&FR_SBUFF_OUT(data, COMMAND_OUTPUT_MAX), &head); + if (slen <= 0) { + fr_assert(0); + RETURN_OK_WITH_ERROR(); } - /* - * Delete the trailing ", ". - */ - if (p > data) p -= 2; - *p = 0; - fr_pair_list_free(&head); - RETURN_OK(p - data); + RETURN_OK(slen); } diff --git a/src/lib/util/pair.h b/src/lib/util/pair.h index 82cb64c5c23..18e886ebc55 100644 --- a/src/lib/util/pair.h +++ b/src/lib/util/pair.h @@ -775,6 +775,8 @@ ssize_t fr_pair_print(fr_sbuff_t *out, fr_pair_t const *parent, ssize_t fr_pair_print_secure(fr_sbuff_t *out, fr_pair_t const *parent, fr_pair_t const *vp) CC_HINT(nonnull(1,3)); +ssize_t fr_pair_list_print(fr_sbuff_t *out, fr_pair_list_t const *list); + static inline fr_slen_t CC_HINT(nonnull(2,4)) fr_pair_aprint(TALLOC_CTX *ctx, char **out, fr_pair_t const *parent, fr_pair_t const *vp) SBUFF_OUT_TALLOC_FUNC_NO_LEN_DEF(fr_pair_print, parent, vp) diff --git a/src/lib/util/pair_print.c b/src/lib/util/pair_print.c index 22bcd8d4988..61e13f58866 100644 --- a/src/lib/util/pair_print.c +++ b/src/lib/util/pair_print.c @@ -199,6 +199,43 @@ ssize_t fr_pair_print_secure(fr_sbuff_t *out, fr_pair_t const *parent, fr_pair_t FR_SBUFF_SET_RETURN(out, &our_out); } +/** Print a pair list + * + * @param[in] out Where to write the string. + * @param[in] list pair list + * @return + * - Length of data written to out. + * - value >= outlen on truncation. + */ +ssize_t fr_pair_list_print(fr_sbuff_t *out, fr_pair_list_t const *list) +{ + fr_pair_t *vp; + fr_sbuff_t our_out = FR_SBUFF(out); + + vp = fr_pair_list_head(list); + if (!vp) { + FR_SBUFF_IN_CHAR_RETURN(out, '\0'); + return fr_sbuff_used(out); + } + + while (true) { + ssize_t slen; + + slen = fr_pair_print(&our_out, NULL, vp); + if (slen <= 0) { + fr_assert(0); + return slen; + } + + vp = fr_pair_list_next(list, vp); + if (!vp) break; + + FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, ", "); + } + + FR_SBUFF_SET_RETURN(out, &our_out); +} + /** Print one attribute and value to FP * * Complete string with '\\t' and '\\n' is written to buffer before printing to