summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-01-11 13:26:44 +0100
committerThomas Haller <thaller@redhat.com>2019-01-22 16:30:23 +0100
commit035c4ad45d75d4ac10c6da5b4138ecd55da6c5f8 (patch)
treed7be76b5d2b3c88c11ccd4962a981260400cc820
parentd7d2dafc1b25bc02a51c32e9660b66e4a987befe (diff)
downloadNetworkManager-035c4ad45d75d4ac10c6da5b4138ecd55da6c5f8.tar.gz
shared: suppress -Wstringop-truncation warning in nm_strndup_a()
The compiler is too smart for nm_strndup_a(). The code is correct, suppress "-Wstringop-truncation" warning.
-rw-r--r--shared/nm-utils/nm-shared-utils.h9
-rw-r--r--shared/nm-utils/tests/test-shared-general.c53
2 files changed, 61 insertions, 1 deletions
diff --git a/shared/nm-utils/nm-shared-utils.h b/shared/nm-utils/nm-shared-utils.h
index 8106371d0a..93868726e8 100644
--- a/shared/nm-utils/nm-shared-utils.h
+++ b/shared/nm-utils/nm-shared-utils.h
@@ -255,10 +255,12 @@ nm_memdup (gconstpointer data, gsize size)
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
@@ -269,7 +271,12 @@ _nm_strndup_a_step (char *s, const char *str, gsize len)
*
* 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. */
+ * 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 = (alloca_maxlen); \
diff --git a/shared/nm-utils/tests/test-shared-general.c b/shared/nm-utils/tests/test-shared-general.c
index d7df46dc52..7d22e56d99 100644
--- a/shared/nm-utils/tests/test-shared-general.c
+++ b/shared/nm-utils/tests/test-shared-general.c
@@ -152,6 +152,58 @@ test_nm_strdup_int (void)
/*****************************************************************************/
+static void
+test_nm_strndup_a (void)
+{
+ int run;
+
+ for (run = 0; run < 20; run++) {
+ gs_free char *input = NULL;
+ char ch;
+ gsize i, l;
+
+ input = g_strnfill (nmtst_get_rand_int () % 20, 'x');
+
+ for (i = 0; input[i]; i++) {
+ while ((ch = ((char) nmtst_get_rand_int ())) == '\0') {
+ /* repeat. */
+ }
+ input[i] = ch;
+ }
+
+ {
+ gs_free char *dup_free = NULL;
+ const char *dup;
+
+ l = strlen (input) + 1;
+ dup = nm_strndup_a (10, input, l - 1, &dup_free);
+ g_assert_cmpstr (dup, ==, input);
+ if (strlen (dup) < 10)
+ g_assert (!dup_free);
+ else
+ g_assert (dup == dup_free);
+ }
+
+ {
+ gs_free char *dup_free = NULL;
+ const char *dup;
+
+ l = nmtst_get_rand_int () % 23;
+ dup = nm_strndup_a (10, input, l, &dup_free);
+ g_assert (strncmp (dup, input, l) == 0);
+ g_assert (strlen (dup) <= l);
+ if (l < 10)
+ g_assert (!dup_free);
+ else
+ g_assert (dup == dup_free);
+ if (strlen (input) < l)
+ g_assert (nm_utils_memeqzero (&dup[strlen (input)], l - strlen (input)));
+ }
+ }
+}
+
+/*****************************************************************************/
+
NMTST_DEFINE ();
int main (int argc, char **argv)
@@ -162,6 +214,7 @@ int main (int argc, char **argv)
g_test_add_func ("/general/test_nmhash", test_nmhash);
g_test_add_func ("/general/test_nm_make_strv", test_make_strv);
g_test_add_func ("/general/test_nm_strdup_int", test_nm_strdup_int);
+ g_test_add_func ("/general/test_nm_strndup_a", test_nm_strndup_a);
return g_test_run ();
}