summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2022-05-09 19:18:48 +0200
committerThomas Haller <thaller@redhat.com>2022-05-09 19:18:48 +0200
commitc6e41b2df35f6d2ad9c8b9d50799dbef3f7e1747 (patch)
tree02b66fa5f1c37ae6d3343c3f1b92541fe6a0e2ef
parent77c8b2960abfc3a7b05ee1bc7dbfe382e9b64a3e (diff)
parent560feecb4c70f40367f18581c9734946de473e02 (diff)
downloadNetworkManager-c6e41b2df35f6d2ad9c8b9d50799dbef3f7e1747.tar.gz
glib-aux: merge branch 'th/str-buf-stack-allocated'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1203
-rw-r--r--src/core/devices/ovs/nm-ovsdb.c2
-rw-r--r--src/core/nm-core-utils.c4
-rw-r--r--src/libnm-core-impl/nm-keyfile-utils.c6
-rw-r--r--src/libnm-core-impl/nm-keyfile.c2
-rw-r--r--src/libnm-core-impl/nm-setting-bridge.c2
-rw-r--r--src/libnm-core-impl/nm-setting-ip-config.c2
-rw-r--r--src/libnm-glib-aux/nm-enum-utils.c2
-rw-r--r--src/libnm-glib-aux/nm-shared-utils.c24
-rw-r--r--src/libnm-glib-aux/nm-str-buf.h75
-rw-r--r--src/libnm-glib-aux/tests/test-shared-general.c59
-rw-r--r--src/libnm-log-core/nm-logging.c2
-rw-r--r--src/libnm-std-aux/nm-std-utils.h4
-rw-r--r--src/libnmc-base/nm-polkit-listener.c5
13 files changed, 136 insertions, 53 deletions
diff --git a/src/core/devices/ovs/nm-ovsdb.c b/src/core/devices/ovs/nm-ovsdb.c
index 7fa394d67d..eb8efe4bf8 100644
--- a/src/core/devices/ovs/nm-ovsdb.c
+++ b/src/core/devices/ovs/nm-ovsdb.c
@@ -1553,7 +1553,7 @@ _external_ids_to_string(const GArray *arr)
if (!arr)
return g_strdup("empty");
- nm_str_buf_init(&strbuf, NM_UTILS_GET_NEXT_REALLOC_SIZE_104, FALSE);
+ strbuf = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_104, FALSE);
nm_str_buf_append(&strbuf, "[");
for (i = 0; i < arr->len; i++) {
const NMUtilsNamedValue *n = &g_array_index(arr, NMUtilsNamedValue, i);
diff --git a/src/core/nm-core-utils.c b/src/core/nm-core-utils.c
index 25d1ec807f..b2ebe30c25 100644
--- a/src/core/nm-core-utils.c
+++ b/src/core/nm-core-utils.c
@@ -5113,7 +5113,7 @@ nm_utils_spawn_helper(const char *const *args,
fcntl(info->child_stdout, F_SETFL, fd_flags | O_NONBLOCK);
/* Watch process stdin */
- nm_str_buf_init(&info->out_buffer, 32, TRUE);
+ info->out_buffer = NM_STR_BUF_INIT(32, TRUE);
for (arg = args; *arg; arg++) {
nm_str_buf_append(&info->out_buffer, *arg);
nm_str_buf_append_c(&info->out_buffer, '\0');
@@ -5127,7 +5127,7 @@ nm_utils_spawn_helper(const char *const *args,
g_source_attach(info->output_source, g_main_context_get_thread_default());
/* Watch process stdout */
- nm_str_buf_init(&info->in_buffer, NM_UTILS_GET_NEXT_REALLOC_SIZE_1000, FALSE);
+ info->in_buffer = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_1000, FALSE);
info->input_source = nm_g_unix_fd_source_new(info->child_stdout,
G_IO_IN | G_IO_ERR | G_IO_HUP,
G_PRIORITY_DEFAULT,
diff --git a/src/libnm-core-impl/nm-keyfile-utils.c b/src/libnm-core-impl/nm-keyfile-utils.c
index c599aefa7b..95073bcc93 100644
--- a/src/libnm-core-impl/nm-keyfile-utils.c
+++ b/src/libnm-core-impl/nm-keyfile-utils.c
@@ -210,7 +210,7 @@ nm_keyfile_plugin_kf_set_integer_list_uint(GKeyFile *kf,
g_return_if_fail(group && group[0]);
g_return_if_fail(key && key[0]);
- nm_str_buf_init(&strbuf, length * 4u + 2u, FALSE);
+ strbuf = NM_STR_BUF_INIT(length * 4u + 2u, FALSE);
for (i = 0; i < length; i++)
nm_str_buf_append_printf(&strbuf, "%u;", data[i]);
nm_keyfile_plugin_kf_set_value(kf, group, key, nm_str_buf_get_str(&strbuf));
@@ -231,7 +231,7 @@ nm_keyfile_plugin_kf_set_integer_list_uint8(GKeyFile *kf,
g_return_if_fail(group && group[0]);
g_return_if_fail(key && key[0]);
- nm_str_buf_init(&strbuf, length * 4u + 2u, FALSE);
+ strbuf = NM_STR_BUF_INIT(length * 4u + 2u, FALSE);
for (i = 0; i < length; i++)
nm_str_buf_append_printf(&strbuf, "%u;", (guint) data[i]);
nm_keyfile_plugin_kf_set_value(kf, group, key, nm_str_buf_get_str(&strbuf));
@@ -542,7 +542,7 @@ _keyfile_key_encode(const char *name, char **out_to_free)
len = i + strlen(&name[i]);
nm_assert(len == strlen(name));
- nm_str_buf_init(&str, len + 15u, FALSE);
+ str = NM_STR_BUF_INIT(len + 15u, FALSE);
if (name[0] == ' ') {
nm_assert(i == 0);
diff --git a/src/libnm-core-impl/nm-keyfile.c b/src/libnm-core-impl/nm-keyfile.c
index bbac7c1e23..76d15cb1a0 100644
--- a/src/libnm-core-impl/nm-keyfile.c
+++ b/src/libnm-core-impl/nm-keyfile.c
@@ -4374,7 +4374,7 @@ nm_keyfile_utils_create_filename(const char *name, gboolean with_extension)
g_return_val_if_fail(name && name[0], NULL);
- nm_str_buf_init(&str, 0, FALSE);
+ str = NM_STR_BUF_INIT(0, FALSE);
len = strlen(name);
diff --git a/src/libnm-core-impl/nm-setting-bridge.c b/src/libnm-core-impl/nm-setting-bridge.c
index 41cd6632f2..fab6e4762e 100644
--- a/src/libnm-core-impl/nm-setting-bridge.c
+++ b/src/libnm-core-impl/nm-setting-bridge.c
@@ -435,7 +435,7 @@ nm_bridge_vlan_to_str(const NMBridgeVlan *vlan, GError **error)
* future if more parameters are added to the object that could
* make it invalid. */
- nm_str_buf_init(&string, NM_UTILS_GET_NEXT_REALLOC_SIZE_32, FALSE);
+ string = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_32, FALSE);
if (vlan->vid_start == vlan->vid_end)
nm_str_buf_append_printf(&string, "%u", vlan->vid_start);
diff --git a/src/libnm-core-impl/nm-setting-ip-config.c b/src/libnm-core-impl/nm-setting-ip-config.c
index 25c2dc5d4a..1bad2e93b0 100644
--- a/src/libnm-core-impl/nm-setting-ip-config.c
+++ b/src/libnm-core-impl/nm-setting-ip-config.c
@@ -3814,7 +3814,7 @@ nm_ip_routing_rule_to_string(const NMIPRoutingRule *self,
}
}
- nm_str_buf_init(&str, NM_UTILS_GET_NEXT_REALLOC_SIZE_32, FALSE);
+ str = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_32, FALSE);
if (self->priority_has) {
nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '),
diff --git a/src/libnm-glib-aux/nm-enum-utils.c b/src/libnm-glib-aux/nm-enum-utils.c
index 3b9b7e8d13..b7f7a3f6cc 100644
--- a/src/libnm-glib-aux/nm-enum-utils.c
+++ b/src/libnm-glib-aux/nm-enum-utils.c
@@ -142,7 +142,7 @@ _nm_utils_enum_to_str_full(GType type,
flags_separator = flags_separator ?: " ";
- nm_str_buf_init(&strbuf, 16, FALSE);
+ strbuf = NM_STR_BUF_INIT(16, FALSE);
for (; value_infos && value_infos->nick; value_infos++) {
nm_assert(_enum_is_valid_flags_nick(value_infos->nick));
diff --git a/src/libnm-glib-aux/nm-shared-utils.c b/src/libnm-glib-aux/nm-shared-utils.c
index f305a7aa13..50512ee10f 100644
--- a/src/libnm-glib-aux/nm-shared-utils.c
+++ b/src/libnm-glib-aux/nm-shared-utils.c
@@ -2998,7 +2998,7 @@ nm_utils_buf_utf8safe_unescape(const char *str,
return str;
}
- nm_str_buf_init(&strbuf, len + 1u, FALSE);
+ strbuf = NM_STR_BUF_INIT(len + 1u, FALSE);
nm_str_buf_append_len(&strbuf, str, s - str);
str = s;
@@ -3165,7 +3165,7 @@ nm_utils_buf_utf8safe_escape(gconstpointer buf,
return str;
}
- nm_str_buf_init(&strbuf, buflen + 5, NM_FLAGS_HAS(flags, NM_UTILS_STR_UTF8_SAFE_FLAG_SECRET));
+ strbuf = NM_STR_BUF_INIT(buflen + 5, NM_FLAGS_HAS(flags, NM_UTILS_STR_UTF8_SAFE_FLAG_SECRET));
s = str;
do {
@@ -5841,10 +5841,22 @@ _nm_str_buf_ensure_size(NMStrBuf *strbuf, gsize new_size, gboolean reserve_exact
new_size = nm_utils_get_next_realloc_size(!strbuf->_priv_do_bzero_mem, new_size);
}
- strbuf->_priv_str = nm_secret_mem_realloc(strbuf->_priv_str,
- strbuf->_priv_do_bzero_mem,
- strbuf->_priv_allocated,
- new_size);
+ if (strbuf->_priv_malloced) {
+ strbuf->_priv_str = nm_secret_mem_realloc(strbuf->_priv_str,
+ strbuf->_priv_do_bzero_mem,
+ strbuf->_priv_allocated,
+ new_size);
+ } else {
+ char *old = strbuf->_priv_str;
+
+ strbuf->_priv_str = g_malloc(new_size);
+ if (strbuf->_priv_len > 0) {
+ memcpy(strbuf->_priv_str, old, strbuf->_priv_len);
+ if (strbuf->_priv_do_bzero_mem)
+ nm_explicit_bzero(old, strbuf->_priv_len);
+ }
+ strbuf->_priv_malloced = TRUE;
+ }
strbuf->_priv_allocated = new_size;
}
diff --git a/src/libnm-glib-aux/nm-str-buf.h b/src/libnm-glib-aux/nm-str-buf.h
index d7a2b3557f..9a3c5baf42 100644
--- a/src/libnm-glib-aux/nm-str-buf.h
+++ b/src/libnm-glib-aux/nm-str-buf.h
@@ -26,6 +26,7 @@ typedef struct _NMStrBuf {
};
bool _priv_do_bzero_mem;
+ bool _priv_malloced;
} NMStrBuf;
/*****************************************************************************/
@@ -36,29 +37,56 @@ _nm_str_buf_assert(const NMStrBuf *strbuf)
nm_assert(strbuf);
nm_assert((!!strbuf->_priv_str) == (strbuf->_priv_allocated > 0));
nm_assert(strbuf->_priv_len <= strbuf->_priv_allocated);
+ nm_assert(!strbuf->_priv_malloced || strbuf->_priv_str);
}
static inline NMStrBuf
-NM_STR_BUF_INIT(gsize allocated, gboolean do_bzero_mem)
+NM_STR_BUF_INIT_FULL(char *str,
+ gsize len,
+ gsize allocated,
+ gboolean malloced,
+ gboolean do_bzero_mem)
{
NMStrBuf strbuf = {
- ._priv_str = allocated ? g_malloc(allocated) : NULL,
+ ._priv_str = allocated > 0 ? str : NULL,
._priv_allocated = allocated,
- ._priv_len = 0,
+ ._priv_len = len,
._priv_do_bzero_mem = do_bzero_mem,
+ ._priv_malloced = allocated > 0 && malloced,
};
+ _nm_str_buf_assert(&strbuf);
+
return strbuf;
}
-static inline void
-nm_str_buf_init(NMStrBuf *strbuf, gsize len, bool do_bzero_mem)
+static inline NMStrBuf
+NM_STR_BUF_INIT(gsize allocated, gboolean do_bzero_mem)
{
- nm_assert(strbuf);
- *strbuf = NM_STR_BUF_INIT(len, do_bzero_mem);
- _nm_str_buf_assert(strbuf);
+ return NM_STR_BUF_INIT_FULL(allocated > 0 ? g_malloc(allocated) : NULL,
+ 0,
+ allocated,
+ allocated > 0,
+ do_bzero_mem);
}
+#define NM_STR_BUF_INIT_A(size, do_bzero_mem) \
+ NM_STR_BUF_INIT_FULL( \
+ g_alloca(size), \
+ 0, \
+ NM_STATIC_ASSERT_EXPR_1((size) > 0 && (size) <= NM_UTILS_GET_NEXT_REALLOC_SIZE_488) \
+ ? (size) \
+ : 0, \
+ FALSE, \
+ (do_bzero_mem));
+
+#define NM_STR_BUF_INIT_ARR(arr, do_bzero_mem) \
+ NM_STR_BUF_INIT_FULL((arr), \
+ 0, \
+ NM_STATIC_ASSERT_EXPR_1(sizeof(arr) > sizeof(char *)) ? sizeof(arr) : 0, \
+ FALSE, \
+ (do_bzero_mem));
+
void _nm_str_buf_ensure_size(NMStrBuf *strbuf, gsize new_size, gboolean reserve_exact);
static inline void
@@ -359,10 +387,10 @@ static inline gboolean
nm_str_buf_is_initalized(NMStrBuf *strbuf)
{
nm_assert(strbuf);
-#if NM_MORE_ASSERTS
- if (strbuf->_priv_str)
- _nm_str_buf_assert(strbuf);
-#endif
+ if (NM_MORE_ASSERTS > 0) {
+ if (strbuf->_priv_str)
+ _nm_str_buf_assert(strbuf);
+ }
return !!strbuf->_priv_str;
}
@@ -463,9 +491,11 @@ nm_str_buf_get_char(const NMStrBuf *strbuf, gsize index)
* Returns: (transfer full): the string of the buffer
* which must be freed by the caller. The @strbuf
* is afterwards in undefined state, though it can be
- * reused after nm_str_buf_init().
- * Note that if no string is allocated yet (after nm_str_buf_init() with
- * length zero), this will return %NULL. */
+ * reused after resetting with NM_STR_BUF_INIT().
+ * Note that if no string is allocated yet (after NM_STR_BUF_INIT() with
+ * length zero), this will return %NULL.
+ *
+ * If the buffer was not malloced before, it will be malloced now. */
static inline char *
nm_str_buf_finalize(NMStrBuf *strbuf, gsize *out_len)
{
@@ -476,6 +506,16 @@ nm_str_buf_finalize(NMStrBuf *strbuf, gsize *out_len)
if (!strbuf->_priv_str)
return NULL;
+ if (!strbuf->_priv_malloced) {
+ char *str = g_steal_pointer(&strbuf->_priv_str);
+ char *result;
+
+ result = g_strndup(str, strbuf->_priv_len);
+ if (strbuf->_priv_do_bzero_mem)
+ nm_explicit_bzero(str, strbuf->_priv_len);
+ return result;
+ }
+
nm_str_buf_maybe_expand(strbuf, 1, TRUE);
strbuf->_priv_str[strbuf->_priv_len] = '\0';
@@ -507,7 +547,7 @@ nm_str_buf_finalize_to_gbytes(NMStrBuf *strbuf)
*
* Frees the associated memory of @strbuf. The buffer
* afterwards is in undefined state, but can be re-initialized
- * with nm_str_buf_init().
+ * with NM_STR_BUF_INIT().
*/
static inline void
nm_str_buf_destroy(NMStrBuf *strbuf)
@@ -517,7 +557,8 @@ nm_str_buf_destroy(NMStrBuf *strbuf)
_nm_str_buf_assert(strbuf);
if (strbuf->_priv_do_bzero_mem)
nm_explicit_bzero(strbuf->_priv_str, strbuf->_priv_len);
- g_free(strbuf->_priv_str);
+ if (strbuf->_priv_malloced)
+ g_free(strbuf->_priv_str);
/* the buffer is in invalid state afterwards, however, we clear it
* so far, that nm_auto_str_buf is happy when calling
diff --git a/src/libnm-glib-aux/tests/test-shared-general.c b/src/libnm-glib-aux/tests/test-shared-general.c
index ccd1b1c37b..5e9310f5ac 100644
--- a/src/libnm-glib-aux/tests/test-shared-general.c
+++ b/src/libnm-glib-aux/tests/test-shared-general.c
@@ -917,27 +917,58 @@ test_nm_str_buf(void)
{
guint i_run;
- for (i_run = 0; TRUE; i_run++) {
- nm_auto_str_buf NMStrBuf strbuf = {};
- nm_auto_free_gstring GString *gstr = NULL;
+ for (i_run = 0; i_run < 1000; i_run++) {
+ char stack_buf[1024];
+ nm_auto_str_buf NMStrBuf strbuf;
+ nm_auto_free_gstring GString *gstr = NULL;
int i, j, k;
int c;
- nm_str_buf_init(&strbuf, nmtst_get_rand_uint32() % 200u + 1u, nmtst_get_rand_bool());
+ switch (nmtst_get_rand_uint32() % 10) {
+ case 0:
+ memset(&strbuf, 0, sizeof(strbuf));
+ break;
+ case 1 ... 4:
+ strbuf = NM_STR_BUF_INIT_FULL(stack_buf,
+ 0,
+ nmtst_get_rand_uint32() % sizeof(stack_buf),
+ FALSE,
+ nmtst_get_rand_bool());
+ break;
+ default:
+ strbuf = NM_STR_BUF_INIT(nmtst_get_rand_uint32() % 200u + 1u, nmtst_get_rand_bool());
+ break;
+ }
- if (i_run < 1000) {
- c = nmtst_get_rand_word_length(NULL);
- for (i = 0; i < c; i++)
- nm_str_buf_append_c(&strbuf, '0' + (i % 10));
- gstr = g_string_new(nm_str_buf_get_str(&strbuf));
- j = nmtst_get_rand_uint32() % (strbuf.len + 1);
- k = nmtst_get_rand_uint32() % (strbuf.len - j + 2) - 1;
+ c = nmtst_get_rand_word_length(NULL);
+ for (i = 0; i < c; i++)
+ nm_str_buf_append_c(&strbuf, '0' + (i % 10));
+ gstr = g_string_new(nm_str_buf_get_str(&strbuf));
+ j = nmtst_get_rand_uint32() % (strbuf.len + 1);
+ k = nmtst_get_rand_uint32() % (strbuf.len - j + 2) - 1;
- nm_str_buf_erase(&strbuf, j, k, nmtst_get_rand_bool());
- g_string_erase(gstr, j, k);
+ nm_str_buf_erase(&strbuf, j, k, nmtst_get_rand_bool());
+ g_string_erase(gstr, j, k);
+ if (gstr->str[0])
g_assert_cmpstr(gstr->str, ==, nm_str_buf_get_str(&strbuf));
+ else
+ g_assert(NM_IN_STRSET(nm_str_buf_get_str(&strbuf), NULL, ""));
+ }
+
+ for (i_run = 0; i_run < 50; i_run++) {
+ char stack_buf[20];
+ nm_auto_str_buf NMStrBuf strbuf = NM_STR_BUF_INIT_ARR(stack_buf, nmtst_get_rand_bool());
+
+ nm_str_buf_append_c_len(&strbuf, 'a', nmtst_get_rand_uint32() % (sizeof(stack_buf) * 2));
+ if (strbuf.len <= sizeof(stack_buf)) {
+ g_assert(stack_buf == nm_str_buf_get_str_unsafe(&strbuf));
} else
- return;
+ g_assert(stack_buf != nm_str_buf_get_str_unsafe(&strbuf));
+
+ if (strbuf.len < sizeof(stack_buf)) {
+ g_assert(stack_buf == nm_str_buf_get_str(&strbuf));
+ } else
+ g_assert(stack_buf != nm_str_buf_get_str(&strbuf));
}
}
diff --git a/src/libnm-log-core/nm-logging.c b/src/libnm-log-core/nm-logging.c
index f464ef296d..5cce508daf 100644
--- a/src/libnm-log-core/nm-logging.c
+++ b/src/libnm-log-core/nm-logging.c
@@ -468,7 +468,7 @@ _domains_to_string(gboolean include_level_override,
* nm_logging_setup(), because we want to expand "DEFAULT" and "ALL".
*/
- nm_str_buf_init(&sbuf, NM_UTILS_GET_NEXT_REALLOC_SIZE_40, FALSE);
+ sbuf = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_40, FALSE);
for (diter = &domain_desc[0]; diter->name; diter++) {
/* If it's set for any lower level, it will also be set for LOGL_ERR */
diff --git a/src/libnm-std-aux/nm-std-utils.h b/src/libnm-std-aux/nm-std-utils.h
index 0d864af9d9..6aa787eb6a 100644
--- a/src/libnm-std-aux/nm-std-utils.h
+++ b/src/libnm-std-aux/nm-std-utils.h
@@ -14,12 +14,12 @@
* certain buffer sizes.
*
* The use of these defines is to get favorable allocation sequences.
- * For example, nm_str_buf_init() asks for an initial allocation size. Note that
+ * For example, NM_STR_BUF_INIT() asks for an initial allocation size. Note that
* it reserves the exactly requested amount, under the assumption that the
* user may know how many bytes will be required. However, often the caller
* doesn't know in advance, and NMStrBuf grows exponentially by calling
* nm_utils_get_next_realloc_size().
- * Imagine you call nm_str_buf_init() with an initial buffer size 100, and you
+ * Imagine you call NM_STR_BUF_INIT() with an initial buffer size 100, and you
* add one character at a time. Then the first reallocation will increase the
* buffer size only from 100 to 104.
* If you however start with an initial buffer size of 104, then the next reallocation
diff --git a/src/libnmc-base/nm-polkit-listener.c b/src/libnmc-base/nm-polkit-listener.c
index 39a06bc6d4..e7972faa48 100644
--- a/src/libnmc-base/nm-polkit-listener.c
+++ b/src/libnmc-base/nm-polkit-listener.c
@@ -393,7 +393,7 @@ queue_string_to_helper(AuthRequest *request, const char *response)
g_return_if_fail(response);
if (!nm_str_buf_is_initalized(&request->out_buffer))
- nm_str_buf_init(&request->out_buffer, strlen(response) + 2u, TRUE);
+ request->out_buffer = NM_STR_BUF_INIT(strlen(response) + 2u, TRUE);
nm_str_buf_append(&request->out_buffer, response);
nm_str_buf_ensure_trailing_c(&request->out_buffer, '\n');
@@ -587,10 +587,9 @@ create_request(NMPolkitListener *listener,
.cookie = g_strdup(cookie),
.request_any_response = FALSE,
.request_is_completed = FALSE,
+ .in_buffer = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_1000, FALSE),
};
- nm_str_buf_init(&request->in_buffer, NM_UTILS_GET_NEXT_REALLOC_SIZE_1000, FALSE);
-
c_list_link_tail(&listener->request_lst_head, &request->request_lst);
return request;
}