diff options
author | Thomas Haller <thaller@redhat.com> | 2019-04-02 12:39:47 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2019-04-04 21:01:15 +0200 |
commit | 26d144d5a030875c3eaf62eb437a270f64ff729a (patch) | |
tree | 71114c46ada32a71d8c1b64c5a49e9eef99224a9 | |
parent | 08c327f8a60e884752092a27195c3f2725a95790 (diff) | |
download | NetworkManager-26d144d5a030875c3eaf62eb437a270f64ff729a.tar.gz |
shared: move nm_memdup(), nm_strndup_a(), and nm_strdup_int() to "nm-macros-internal.h"
The main difference between "shared/nm-utils/nm-macros-internal.h" and
"shared/nm-utils/nm-shared-utils.h" is that the former is header-only
while the latter has a source file as well.
Apart from that, both headers are included everywhere.
The next commit will add nm_strstrip_avoid_copy_a() to
"nm-macros-internal.h" header, which will use nm_strndup_a().
Hence, also nm_strndup_a() should be in "nm-macros-internal.h".
-rw-r--r-- | shared/nm-utils/nm-macros-internal.h | 112 | ||||
-rw-r--r-- | shared/nm-utils/nm-shared-utils.h | 112 |
2 files changed, 112 insertions, 112 deletions
diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h index 33ed5980d4..b2668f8e37 100644 --- a/shared/nm-utils/nm-macros-internal.h +++ b/shared/nm-utils/nm-macros-internal.h @@ -1464,6 +1464,118 @@ nm_strcmp_p (gconstpointer a, gconstpointer b) /*****************************************************************************/ +/* like g_memdup(). The difference is that the @size argument is of type + * gsize, while g_memdup() has type guint. Since, the size of container types + * like GArray is guint as well, this means trying to g_memdup() an + * array, + * g_memdup (array->data, array->len * sizeof (ElementType)) + * will lead to integer overflow, if there are more than G_MAXUINT/sizeof(ElementType) + * bytes. That seems unnecessarily dangerous to me. + * nm_memdup() avoids that, because its size argument is always large enough + * to contain all data that a GArray can hold. + * + * Another minor difference to g_memdup() is that the glib version also + * returns %NULL if @data is %NULL. E.g. g_memdup(NULL, 1) + * gives %NULL, but nm_memdup(NULL, 1) crashes. I think that + * is desirable, because @size MUST be correct at all times. @size + * may be zero, but one must not claim to have non-zero bytes when + * passing a %NULL @data pointer. + */ +static inline gpointer +nm_memdup (gconstpointer data, gsize size) +{ + gpointer p; + + if (size == 0) + return NULL; + p = g_malloc (size); + memcpy (p, data, size); + return p; +} + +static inline char * +_nm_strndup_a_step (char *s, const char *str, gsize len) +{ + NM_PRAGMA_WARNING_DISABLE ("-Wstringop-truncation"); + if (len > 0) + strncpy (s, str, len); + s[len] = '\0'; + return s; + NM_PRAGMA_WARNING_REENABLE; +} + +/* Similar to g_strndup(), however, if the string (including the terminating + * NUL char) fits into alloca_maxlen, this will alloca() the memory. + * + * It's a mix of strndup() and strndupa(), but deciding based on @alloca_maxlen + * which one to use. + * + * In case malloc() is necessary, @out_str_free will be set (this string + * must be freed afterwards). It is permissible to pass %NULL as @out_str_free, + * if you ensure that len < alloca_maxlen. + * + * Note that just like g_strndup(), this always returns a buffer with @len + 1 + * bytes, even if strlen(@str) is shorter than that (NUL terminated early). We fill + * the buffer with strncpy(), which means, that @str is copied up to the first + * NUL character and then filled with NUL characters. */ +#define nm_strndup_a(alloca_maxlen, str, len, out_str_free) \ + ({ \ + const gsize _alloca_maxlen_snd = (alloca_maxlen); \ + const char *const _str_snd = (str); \ + const gsize _len_snd = (len); \ + char **const _out_str_free_snd = (out_str_free); \ + char *_s_snd; \ + \ + G_STATIC_ASSERT_EXPR ((alloca_maxlen) <= 300); \ + \ + if ( _out_str_free_snd \ + && _len_snd >= _alloca_maxlen_snd) { \ + _s_snd = g_malloc (_len_snd + 1); \ + *_out_str_free_snd = _s_snd; \ + } else { \ + g_assert (_len_snd < _alloca_maxlen_snd); \ + _s_snd = g_alloca (_len_snd + 1); \ + } \ + _nm_strndup_a_step (_s_snd, _str_snd, _len_snd); \ + }) + +/*****************************************************************************/ + +/* generic macro to convert an int to a (heap allocated) string. + * + * Usually, an inline function nm_strdup_int64() would be enough. However, + * that cannot be used for guint64. So, we would also need nm_strdup_uint64(). + * This causes subtle error potential, because the caller needs to ensure to + * use the right one (and compiler isn't going to help as it silently casts). + * + * Instead, this generic macro is supposed to handle all integers correctly. */ +#if _NM_CC_SUPPORT_GENERIC +#define nm_strdup_int(val) \ + _Generic ((val), \ + char: g_strdup_printf ("%d", (int) (val)), \ + \ + signed char: g_strdup_printf ("%d", (signed) (val)), \ + signed short: g_strdup_printf ("%d", (signed) (val)), \ + signed: g_strdup_printf ("%d", (signed) (val)), \ + signed long: g_strdup_printf ("%ld", (signed long) (val)), \ + signed long long: g_strdup_printf ("%lld", (signed long long) (val)), \ + \ + unsigned char: g_strdup_printf ("%u", (unsigned) (val)), \ + unsigned short: g_strdup_printf ("%u", (unsigned) (val)), \ + unsigned: g_strdup_printf ("%u", (unsigned) (val)), \ + unsigned long: g_strdup_printf ("%lu", (unsigned long) (val)), \ + unsigned long long: g_strdup_printf ("%llu", (unsigned long long) (val)) \ + ) +#else +#define nm_strdup_int(val) \ + ( ( sizeof (val) == sizeof (guint64) \ + && ((typeof (val)) -1) > 0) \ + ? g_strdup_printf ("%"G_GUINT64_FORMAT, (guint64) (val)) \ + : g_strdup_printf ("%"G_GINT64_FORMAT, (gint64) (val))) +#endif + +/*****************************************************************************/ + static inline guint nm_encode_version (guint major, guint minor, guint micro) { diff --git a/shared/nm-utils/nm-shared-utils.h b/shared/nm-utils/nm-shared-utils.h index 3132d155b1..95ed5c946f 100644 --- a/shared/nm-utils/nm-shared-utils.h +++ b/shared/nm-utils/nm-shared-utils.h @@ -258,118 +258,6 @@ gboolean nm_utils_memeqzero (gconstpointer data, gsize length); /*****************************************************************************/ -/* like g_memdup(). The difference is that the @size argument is of type - * gsize, while g_memdup() has type guint. Since, the size of container types - * like GArray is guint as well, this means trying to g_memdup() an - * array, - * g_memdup (array->data, array->len * sizeof (ElementType)) - * will lead to integer overflow, if there are more than G_MAXUINT/sizeof(ElementType) - * bytes. That seems unnecessarily dangerous to me. - * nm_memdup() avoids that, because its size argument is always large enough - * to contain all data that a GArray can hold. - * - * Another minor difference to g_memdup() is that the glib version also - * returns %NULL if @data is %NULL. E.g. g_memdup(NULL, 1) - * gives %NULL, but nm_memdup(NULL, 1) crashes. I think that - * is desirable, because @size MUST be correct at all times. @size - * may be zero, but one must not claim to have non-zero bytes when - * passing a %NULL @data pointer. - */ -static inline gpointer -nm_memdup (gconstpointer data, gsize size) -{ - gpointer p; - - if (size == 0) - return NULL; - p = g_malloc (size); - memcpy (p, data, size); - return p; -} - -static inline char * -_nm_strndup_a_step (char *s, const char *str, gsize len) -{ - NM_PRAGMA_WARNING_DISABLE ("-Wstringop-truncation"); - if (len > 0) - strncpy (s, str, len); - s[len] = '\0'; - return s; - NM_PRAGMA_WARNING_REENABLE; -} - -/* Similar to g_strndup(), however, if the string (including the terminating - * NUL char) fits into alloca_maxlen, this will alloca() the memory. - * - * It's a mix of strndup() and strndupa(), but deciding based on @alloca_maxlen - * which one to use. - * - * In case malloc() is necessary, @out_str_free will be set (this string - * must be freed afterwards). It is permissible to pass %NULL as @out_str_free, - * if you ensure that len < alloca_maxlen. - * - * Note that just like g_strndup(), this always returns a buffer with @len + 1 - * bytes, even if strlen(@str) is shorter than that (NUL terminated early). We fill - * the buffer with strncpy(), which means, that @str is copied up to the first - * NUL character and then filled with NUL characters. */ -#define nm_strndup_a(alloca_maxlen, str, len, out_str_free) \ - ({ \ - const gsize _alloca_maxlen_snd = (alloca_maxlen); \ - const char *const _str_snd = (str); \ - const gsize _len_snd = (len); \ - char **const _out_str_free_snd = (out_str_free); \ - char *_s_snd; \ - \ - G_STATIC_ASSERT_EXPR ((alloca_maxlen) <= 300); \ - \ - if ( _out_str_free_snd \ - && _len_snd >= _alloca_maxlen_snd) { \ - _s_snd = g_malloc (_len_snd + 1); \ - *_out_str_free_snd = _s_snd; \ - } else { \ - g_assert (_len_snd < _alloca_maxlen_snd); \ - _s_snd = g_alloca (_len_snd + 1); \ - } \ - _nm_strndup_a_step (_s_snd, _str_snd, _len_snd); \ - }) - -/*****************************************************************************/ - -/* generic macro to convert an int to a (heap allocated) string. - * - * Usually, an inline function nm_strdup_int64() would be enough. However, - * that cannot be used for guint64. So, we would also need nm_strdup_uint64(). - * This causes subtle error potential, because the caller needs to ensure to - * use the right one (and compiler isn't going to help as it silently casts). - * - * Instead, this generic macro is supposed to handle all integers correctly. */ -#if _NM_CC_SUPPORT_GENERIC -#define nm_strdup_int(val) \ - _Generic ((val), \ - char: g_strdup_printf ("%d", (int) (val)), \ - \ - signed char: g_strdup_printf ("%d", (signed) (val)), \ - signed short: g_strdup_printf ("%d", (signed) (val)), \ - signed: g_strdup_printf ("%d", (signed) (val)), \ - signed long: g_strdup_printf ("%ld", (signed long) (val)), \ - signed long long: g_strdup_printf ("%lld", (signed long long) (val)), \ - \ - unsigned char: g_strdup_printf ("%u", (unsigned) (val)), \ - unsigned short: g_strdup_printf ("%u", (unsigned) (val)), \ - unsigned: g_strdup_printf ("%u", (unsigned) (val)), \ - unsigned long: g_strdup_printf ("%lu", (unsigned long) (val)), \ - unsigned long long: g_strdup_printf ("%llu", (unsigned long long) (val)) \ - ) -#else -#define nm_strdup_int(val) \ - ( ( sizeof (val) == sizeof (guint64) \ - && ((typeof (val)) -1) > 0) \ - ? g_strdup_printf ("%"G_GUINT64_FORMAT, (guint64) (val)) \ - : g_strdup_printf ("%"G_GINT64_FORMAT, (gint64) (val))) -#endif - -/*****************************************************************************/ - extern const void *const _NM_PTRARRAY_EMPTY[1]; #define NM_PTRARRAY_EMPTY(type) ((type const*) _NM_PTRARRAY_EMPTY) |