From 5ea2fc776cea9f414f4dd49211b50fe4d378aa2c Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sun, 27 Nov 2016 13:47:26 +0100 Subject: [PATCH 1/5] libnm/trivial: move code --- libnm-core/nm-utils.c | 154 +++++++++++++++++++++--------------------- 1 file changed, 77 insertions(+), 77 deletions(-) diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index e52533a949..7fa4cbd97b 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -3013,6 +3013,57 @@ nm_utils_hwaddr_len (int type) g_return_val_if_reached (0); } +static guint8 * +hwaddr_aton (const char *asc, guint8 *buffer, gsize buffer_length, gsize *out_len) +{ + const char *in = asc; + guint8 *out = buffer; + guint8 delimiter = '\0'; + + nm_assert (asc); + nm_assert (buffer); + nm_assert (buffer_length); + nm_assert (out_len); + + while (TRUE) { + const guint8 d1 = in[0]; + guint8 d2; + + if (!g_ascii_isxdigit (d1)) + return NULL; + +#define HEXVAL(c) ((c) <= '9' ? (c) - '0' : ((c) & 0x4F) - ('A' - 10)) + + /* If there's no leading zero (ie "aa:b:cc") then fake it */ + d2 = in[1]; + if (d2 && g_ascii_isxdigit (d2)) { + *out++ = (HEXVAL (d1) << 4) + HEXVAL (d2); + d2 = in[2]; + in += 3; + } else { + /* Fake leading zero */ + *out++ = HEXVAL (d1); + in += 2; + } + + if (!d2) + break; + if (--buffer_length == 0) + return NULL; + + if (d2 != delimiter) { + if ( delimiter == '\0' + && (d2 == ':' || d2 == '-')) + delimiter = d2; + else + return NULL; + } + } + + *out_len = out - buffer; + return buffer; +} + /** * nm_utils_hexstr2bin: * @hex: a string of hexadecimal characters with optional ':' separators @@ -3069,57 +3120,6 @@ nm_utils_hexstr2bin (const char *hex) return g_bytes_new (c, x); } -static guint8 * -hwaddr_aton (const char *asc, guint8 *buffer, gsize buffer_length, gsize *out_len) -{ - const char *in = asc; - guint8 *out = buffer; - guint8 delimiter = '\0'; - - nm_assert (asc); - nm_assert (buffer); - nm_assert (buffer_length); - nm_assert (out_len); - - while (TRUE) { - const guint8 d1 = in[0]; - guint8 d2; - - if (!g_ascii_isxdigit (d1)) - return NULL; - -#define HEXVAL(c) ((c) <= '9' ? (c) - '0' : ((c) & 0x4F) - ('A' - 10)) - - /* If there's no leading zero (ie "aa:b:cc") then fake it */ - d2 = in[1]; - if (d2 && g_ascii_isxdigit (d2)) { - *out++ = (HEXVAL (d1) << 4) + HEXVAL (d2); - d2 = in[2]; - in += 3; - } else { - /* Fake leading zero */ - *out++ = HEXVAL (d1); - in += 2; - } - - if (!d2) - break; - if (--buffer_length == 0) - return NULL; - - if (d2 != delimiter) { - if ( delimiter == '\0' - && (d2 == ':' || d2 == '-')) - delimiter = d2; - else - return NULL; - } - } - - *out_len = out - buffer; - return buffer; -} - /** * nm_utils_hwaddr_atoba: * @asc: the ASCII representation of a hardware address @@ -3212,6 +3212,32 @@ nm_utils_hwaddr_aton (const char *asc, gpointer buffer, gsize length) return buffer; } +static void +_bin2str_buf (gconstpointer addr, gsize length, gboolean upper_case, char *out) +{ + const guint8 *in = addr; + const char *LOOKUP = upper_case ? "0123456789ABCDEF" : "0123456789abcdef"; + + nm_assert (addr); + nm_assert (out); + nm_assert (length > 0); + + /* @out must contain at least @length*3 bytes */ + + for (;;) { + const guint8 v = *in++; + + *out++ = LOOKUP[v >> 4]; + *out++ = LOOKUP[v & 0x0F]; + length--; + if (!length) + break; + *out++ = ':'; + } + + *out = 0; +} + /** * nm_utils_bin2hexstr: * @src: (type guint8) (array length=len): an array of bytes @@ -3257,32 +3283,6 @@ nm_utils_bin2hexstr (gconstpointer src, gsize len, int final_len) return result; } -static void -_bin2str_buf (gconstpointer addr, gsize length, gboolean upper_case, char *out) -{ - const guint8 *in = addr; - const char *LOOKUP = upper_case ? "0123456789ABCDEF" : "0123456789abcdef"; - - nm_assert (addr); - nm_assert (out); - nm_assert (length > 0); - - /* @out must contain at least @length*3 bytes */ - - for (;;) { - const guint8 v = *in++; - - *out++ = LOOKUP[v >> 4]; - *out++ = LOOKUP[v & 0x0F]; - length--; - if (!length) - break; - *out++ = ':'; - } - - *out = 0; -} - static char * _bin2str (gconstpointer addr, gsize length, gboolean upper_case) { From 542d1c257d4bbdf534a2d90aefa895c8de036163 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sun, 27 Nov 2016 13:46:42 +0100 Subject: [PATCH 2/5] libnm: implement nm_utils_bin2hexstr() via _bin2str_buf() --- libnm-core/nm-utils.c | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index 7fa4cbd97b..bfbb93d636 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -3213,7 +3213,7 @@ nm_utils_hwaddr_aton (const char *asc, gpointer buffer, gsize length) } static void -_bin2str_buf (gconstpointer addr, gsize length, gboolean upper_case, char *out) +_bin2str_buf (gconstpointer addr, gsize length, const char delimiter, gboolean upper_case, char *out) { const guint8 *in = addr; const char *LOOKUP = upper_case ? "0123456789ABCDEF" : "0123456789abcdef"; @@ -3222,7 +3222,8 @@ _bin2str_buf (gconstpointer addr, gsize length, gboolean upper_case, char *out) nm_assert (out); nm_assert (length > 0); - /* @out must contain at least @length*3 bytes */ + /* @out must contain at least @length*3 bytes if @delimiter is set, + * otherwise, @length*2+1. */ for (;;) { const guint8 v = *in++; @@ -3232,7 +3233,8 @@ _bin2str_buf (gconstpointer addr, gsize length, gboolean upper_case, char *out) length--; if (!length) break; - *out++ = ':'; + if (delimiter) + *out++ = delimiter; } *out = 0; @@ -3250,35 +3252,22 @@ _bin2str_buf (gconstpointer addr, gsize length, gboolean upper_case, char *out) * * Return value: (transfer full): the textual form of @bytes */ -/* - * Code originally by Alex Larsson and - * copyright Red Hat, Inc. under terms of the LGPL. - */ char * nm_utils_bin2hexstr (gconstpointer src, gsize len, int final_len) { - static char hex_digits[] = "0123456789abcdef"; - const guint8 *bytes = src; char *result; - int i; gsize buflen = (len * 2) + 1; - g_return_val_if_fail (bytes != NULL, NULL); - g_return_val_if_fail (len > 0, NULL); - g_return_val_if_fail (len < 4096, NULL); /* Arbitrary limit */ - if (final_len > -1) - g_return_val_if_fail (final_len < buflen, NULL); + g_return_val_if_fail (src != NULL, NULL); + g_return_val_if_fail (len > 0 && (buflen - 1) / 2 == len, NULL); + g_return_val_if_fail (final_len < 0 || (gsize) final_len < buflen, NULL); + + result = g_malloc (buflen); + _bin2str_buf (src, len, '\0', FALSE, result); - result = g_malloc0 (buflen); - for (i = 0; i < len; i++) { - result[2*i] = hex_digits[(bytes[i] >> 4) & 0xf]; - result[2*i+1] = hex_digits[bytes[i] & 0xf]; - } /* Cut converted key off at the correct length for this cipher type */ - if (final_len > -1) + if (final_len >= 0 && final_len < buflen) result[final_len] = '\0'; - else - result[buflen - 1] = '\0'; return result; } @@ -3292,7 +3281,7 @@ _bin2str (gconstpointer addr, gsize length, gboolean upper_case) nm_assert (length > 0); result = g_malloc (length * 3); - _bin2str_buf (addr, length, upper_case, result); + _bin2str_buf (addr, length, ':', upper_case, result); return result; } @@ -3323,7 +3312,7 @@ nm_utils_hwaddr_ntoa_buf (gconstpointer addr, gsize addr_len, gboolean upper_cas if (buf_len < addr_len * 3) g_return_val_if_reached (NULL); - _bin2str_buf (addr, addr_len, TRUE, buf); + _bin2str_buf (addr, addr_len, ':', TRUE, buf); return buf; } From 4cc2f8906cf9fd1cb763b5b809478874d3d896e4 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sun, 27 Nov 2016 13:57:13 +0100 Subject: [PATCH 3/5] libnm: drop _bin2str() util It was only used by two places, inline it. --- libnm-core/nm-utils.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index bfbb93d636..e766516b3a 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -3272,19 +3272,6 @@ nm_utils_bin2hexstr (gconstpointer src, gsize len, int final_len) return result; } -static char * -_bin2str (gconstpointer addr, gsize length, gboolean upper_case) -{ - char *result; - - nm_assert (addr); - nm_assert (length > 0); - - result = g_malloc (length * 3); - _bin2str_buf (addr, length, ':', upper_case, result); - return result; -} - /** * nm_utils_hwaddr_ntoa: * @addr: (type guint8) (array length=length): a binary hardware address @@ -3297,10 +3284,14 @@ _bin2str (gconstpointer addr, gsize length, gboolean upper_case) char * nm_utils_hwaddr_ntoa (gconstpointer addr, gsize length) { + char *result; + g_return_val_if_fail (addr, g_strdup ("")); g_return_val_if_fail (length > 0, g_strdup ("")); - return _bin2str (addr, length, TRUE); + result = g_malloc (length * 3); + _bin2str_buf (addr, length, ':', TRUE, result); + return result; } const char * @@ -3329,10 +3320,14 @@ nm_utils_hwaddr_ntoa_buf (gconstpointer addr, gsize addr_len, gboolean upper_cas char * _nm_utils_bin2str (gconstpointer addr, gsize length, gboolean upper_case) { + char *result; + g_return_val_if_fail (addr, g_strdup ("")); g_return_val_if_fail (length > 0, g_strdup ("")); - return _bin2str (addr, length, upper_case); + result = g_malloc (length * 3); + _bin2str_buf (addr, length, ':', upper_case, result); + return result; } /** From d7e535aee5a80d12730b14477080f7853e4bd57e Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 28 Nov 2016 08:43:20 +0100 Subject: [PATCH 4/5] libnm/trivial: rename internal function _bin2str() --- libnm-core/nm-utils.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index e766516b3a..5f11ebff31 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -3213,7 +3213,7 @@ nm_utils_hwaddr_aton (const char *asc, gpointer buffer, gsize length) } static void -_bin2str_buf (gconstpointer addr, gsize length, const char delimiter, gboolean upper_case, char *out) +_bin2str (gconstpointer addr, gsize length, const char delimiter, gboolean upper_case, char *out) { const guint8 *in = addr; const char *LOOKUP = upper_case ? "0123456789ABCDEF" : "0123456789abcdef"; @@ -3263,7 +3263,7 @@ nm_utils_bin2hexstr (gconstpointer src, gsize len, int final_len) g_return_val_if_fail (final_len < 0 || (gsize) final_len < buflen, NULL); result = g_malloc (buflen); - _bin2str_buf (src, len, '\0', FALSE, result); + _bin2str (src, len, '\0', FALSE, result); /* Cut converted key off at the correct length for this cipher type */ if (final_len >= 0 && final_len < buflen) @@ -3290,7 +3290,7 @@ nm_utils_hwaddr_ntoa (gconstpointer addr, gsize length) g_return_val_if_fail (length > 0, g_strdup ("")); result = g_malloc (length * 3); - _bin2str_buf (addr, length, ':', TRUE, result); + _bin2str (addr, length, ':', TRUE, result); return result; } @@ -3303,7 +3303,7 @@ nm_utils_hwaddr_ntoa_buf (gconstpointer addr, gsize addr_len, gboolean upper_cas if (buf_len < addr_len * 3) g_return_val_if_reached (NULL); - _bin2str_buf (addr, addr_len, ':', TRUE, buf); + _bin2str (addr, addr_len, ':', TRUE, buf); return buf; } @@ -3326,7 +3326,7 @@ _nm_utils_bin2str (gconstpointer addr, gsize length, gboolean upper_case) g_return_val_if_fail (length > 0, g_strdup ("")); result = g_malloc (length * 3); - _bin2str_buf (addr, length, ':', upper_case, result); + _bin2str (addr, length, ':', upper_case, result); return result; } From 3aa41c6e17d83e85b435791df2044ab064f3a6d9 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sun, 27 Nov 2016 14:47:07 +0100 Subject: [PATCH 5/5] libnm: merge hwaddr_aton() and nm_utils_hexstr2bin() Have nm_utils_hexstr2bin() take over the allocated buffer via g_bytes_new_take(). --- libnm-core/nm-utils.c | 93 +++++++++++++++++---------------- libnm-core/tests/test-general.c | 4 ++ 2 files changed, 52 insertions(+), 45 deletions(-) diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index 5f11ebff31..00a4df7aed 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -3014,10 +3014,16 @@ nm_utils_hwaddr_len (int type) } static guint8 * -hwaddr_aton (const char *asc, guint8 *buffer, gsize buffer_length, gsize *out_len) +_str2bin (const char *asc, + gboolean delimiter_required, + const char *delimiter_candidates, + guint8 *buffer, + gsize buffer_length, + gsize *out_len) { const char *in = asc; guint8 *out = buffer; + gboolean delimiter_has = TRUE; guint8 delimiter = '\0'; nm_assert (asc); @@ -3039,24 +3045,43 @@ hwaddr_aton (const char *asc, guint8 *buffer, gsize buffer_length, gsize *out_le if (d2 && g_ascii_isxdigit (d2)) { *out++ = (HEXVAL (d1) << 4) + HEXVAL (d2); d2 = in[2]; - in += 3; + if (!d2) + break; + in += 2; } else { /* Fake leading zero */ *out++ = HEXVAL (d1); - in += 2; + if (!d2) { + if (!delimiter_has) { + /* when using no delimiter, there must be pairs of hex chars */ + return NULL; + } + break; + } + in += 1; } - if (!d2) - break; if (--buffer_length == 0) return NULL; - if (d2 != delimiter) { - if ( delimiter == '\0' - && (d2 == ':' || d2 == '-')) - delimiter = d2; - else - return NULL; + if (delimiter_has) { + if (d2 != delimiter) { + if (delimiter) + return NULL; + if (delimiter_candidates) { + while (delimiter_candidates[0]) { + if (delimiter_candidates++[0] == d2) + delimiter = d2; + } + } + if (!delimiter) { + if (delimiter_required) + return NULL; + delimiter_has = FALSE; + continue; + } + } + in++; } } @@ -3064,6 +3089,8 @@ hwaddr_aton (const char *asc, guint8 *buffer, gsize buffer_length, gsize *out_le return buffer; } +#define hwaddr_aton(asc, buffer, buffer_length, out_len) _str2bin ((asc), TRUE, ":-", (buffer), (buffer_length), (out_len)) + /** * nm_utils_hexstr2bin: * @hex: a string of hexadecimal characters with optional ':' separators @@ -3078,46 +3105,22 @@ hwaddr_aton (const char *asc, guint8 *buffer, gsize buffer_length, gsize *out_le GBytes * nm_utils_hexstr2bin (const char *hex) { - guint i = 0, x = 0; - gs_free guint8 *c = NULL; - int a, b; - gboolean found_colon = FALSE; + guint8 *buffer; + gsize buffer_length, len; g_return_val_if_fail (hex != NULL, NULL); - if (strncasecmp (hex, "0x", 2) == 0) + if (hex[0] == '0' && hex[1] == 'x') hex += 2; - found_colon = !!strchr (hex, ':'); - c = g_malloc (strlen (hex) / 2 + 1); - for (;;) { - a = g_ascii_xdigit_value (hex[i++]); - if (a < 0) - return NULL; - - if (hex[i] && hex[i] != ':') { - b = g_ascii_xdigit_value (hex[i++]); - if (b < 0) - return NULL; - c[x++] = ((guint) a << 4) | ((guint) b); - } else - c[x++] = (guint) a; - - if (!hex[i]) - break; - if (hex[i] == ':') { - if (!hex[i + 1]) { - /* trailing ':' is invalid */ - return NULL; - } - i++; - } else if (found_colon) { - /* If colons exist, they must delimit 1 or 2 hex chars */ - return NULL; - } + buffer_length = strlen (hex) / 2 + 3; + buffer = g_malloc (buffer_length); + if (!_str2bin (hex, FALSE, ":", buffer, buffer_length, &len)) { + g_free (buffer); + return NULL; } - - return g_bytes_new (c, x); + buffer = g_realloc (buffer, len); + return g_bytes_new_take (buffer, len); } /** diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index 68724721e4..1cb8d7af99 100644 --- a/libnm-core/tests/test-general.c +++ b/libnm-core/tests/test-general.c @@ -4294,6 +4294,10 @@ test_hexstr2bin (void) { "0xccddeeff", { 0xcc, 0xdd, 0xee, 0xff }, 4 }, { "1:2:66:77:80", { 0x01, 0x02, 0x66, 0x77, 0x80 }, 5 }, { "e", { 0x0e }, 1 }, + { "ef", { 0xef }, 1 }, + { "efa" }, + { "efad", { 0xef, 0xad }, 2 }, + { "ef:a", { 0xef, 0x0a }, 2 }, { "aabb1199:" }, { ":aabb1199" }, { "aabb$$dd" },