diff options
author | Thomas Haller <thaller@redhat.com> | 2022-05-09 19:18:48 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2022-05-09 19:18:48 +0200 |
commit | c6e41b2df35f6d2ad9c8b9d50799dbef3f7e1747 (patch) | |
tree | 02b66fa5f1c37ae6d3343c3f1b92541fe6a0e2ef | |
parent | 77c8b2960abfc3a7b05ee1bc7dbfe382e9b64a3e (diff) | |
parent | 560feecb4c70f40367f18581c9734946de473e02 (diff) |
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.c | 2 | ||||
-rw-r--r-- | src/core/nm-core-utils.c | 4 | ||||
-rw-r--r-- | src/libnm-core-impl/nm-keyfile-utils.c | 6 | ||||
-rw-r--r-- | src/libnm-core-impl/nm-keyfile.c | 2 | ||||
-rw-r--r-- | src/libnm-core-impl/nm-setting-bridge.c | 2 | ||||
-rw-r--r-- | src/libnm-core-impl/nm-setting-ip-config.c | 2 | ||||
-rw-r--r-- | src/libnm-glib-aux/nm-enum-utils.c | 2 | ||||
-rw-r--r-- | src/libnm-glib-aux/nm-shared-utils.c | 24 | ||||
-rw-r--r-- | src/libnm-glib-aux/nm-str-buf.h | 75 | ||||
-rw-r--r-- | src/libnm-glib-aux/tests/test-shared-general.c | 59 | ||||
-rw-r--r-- | src/libnm-log-core/nm-logging.c | 2 | ||||
-rw-r--r-- | src/libnm-std-aux/nm-std-utils.h | 4 | ||||
-rw-r--r-- | src/libnmc-base/nm-polkit-listener.c | 5 |
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; } |