[PATCH iproute2 1/3] utils: add hexstring_alloc and print_hexstring helpers
From: Stephen Hemminger <stephen@networkplumber.org>
Date: 2026-07-23 19:15:18
Subsystem:
library code, the rest · Maintainers:
Andrew Morton, Linus Torvalds
hexstring_n2a() writes into a caller-supplied buffer and silently truncates when it is too small: the loop stops once fewer than three bytes remain and returns the partial string. Callers using a fixed SPRINT_BUF therefore drop trailing bytes for keys wider than 31 bytes. Add hexstring_alloc(), which formats into a buffer sized to the input so the full value is always emitted, and print_hexstring(), a wrapper that formats and prints a binary attribute in one call with no local buffer to size. print_hexstring() covers the common print_string(..., hexstring_n2a(...)) pattern. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> --- include/json_print.h | 3 +++ include/utils.h | 1 + lib/json_print.c | 12 ++++++++++++ lib/utils.c | 21 +++++++++++++++++++++ 4 files changed, 37 insertions(+)
diff --git a/include/json_print.h b/include/json_print.h
index c0d6315f..6a458189 100644
--- a/include/json_print.h
+++ b/include/json_print.h@@ -84,6 +84,9 @@ _PRINT_FUNC(float, double) _PRINT_FUNC(tv, const struct timeval *) #undef _PRINT_FUNC +void print_hexstring(const char *key, const char *fmt, + const __u8 *data, unsigned int len); + #define _PRINT_NAME_VALUE_FUNC(type_name, type, format_char) \ void print_##type_name##_name_value(const char *name, type value) \
diff --git a/include/utils.h b/include/utils.h
index f0d45bad..6a8872bf 100644
--- a/include/utils.h
+++ b/include/utils.h@@ -162,6 +162,7 @@ int get_size64(__u64 *size, const char *str); int hex2mem(const char *buf, uint8_t *mem, int count); char *hexstring_n2a(const __u8 *str, int len, char *buf, int blen); +char *hexstring_alloc(const __u8 *str, unsigned int len); __u8 *hexstring_a2n(const char *str, __u8 *buf, int blen, unsigned int *len); #define ADDR64_BUF_SIZE sizeof("xxxx:xxxx:xxxx:xxxx") int addr64_n2a(__u64 addr, char *buff, size_t len);
diff --git a/lib/json_print.c b/lib/json_print.c
index 810d496e..21589073 100644
--- a/lib/json_print.c
+++ b/lib/json_print.c@@ -179,6 +179,18 @@ int print_color_string(enum output_type type, return ret; } +/* Print binary data as a hex string. The buffer is sized to the input, + * so keys of any length are printed in full rather than truncated. + */ +void print_hexstring(const char *key, const char *fmt, + const __u8 *data, unsigned int len) +{ + char *hex = hexstring_alloc(data, len); + + print_string(PRINT_ANY, key, fmt, hex ? : ""); + free(hex); +} + /* * value's type is bool. When using this function in FP context you can't pass * a value to it, you will need to use "is_json_context()" to have different
diff --git a/lib/utils.c b/lib/utils.c
index 50602e59..7a1d8b48 100644
--- a/lib/utils.c
+++ b/lib/utils.c@@ -1186,6 +1186,27 @@ char *hexstring_n2a(const __u8 *str, int len, char *buf, int blen) return buf; } +/* Format binary as hex into a freshly allocated string; caller frees. + * Unlike hexstring_n2a() the result is always sized to hold the full + * input, so there is no silent truncation. Returns NULL on allocation + * failure. + */ +char *hexstring_alloc(const __u8 *str, unsigned int len) +{ + char *buf, *ptr; + unsigned int i; + + buf = malloc(2 * len + 1); + if (!buf) + return NULL; + + for (i = 0, ptr = buf; i < len; i++, ptr += 2) + sprintf(ptr, "%02x", str[i]); + *ptr = '\0'; + + return buf; +} + __u8 *hexstring_a2n(const char *str, __u8 *buf, int blen, unsigned int *len) { unsigned int cnt = 0;
--
2.53.0