@cryptotaxi247 / netdata-1 / commits / 141394aef

Remove VLA (variable-length arrays) (claim and daemon) (#22114)

thiagoftsm committed Apr 14, 2026 at 18:21 UTC 141394aefdb994e88f9eb09b15857dd34d81e833
12 files changed +60 -50
src/claim/claim-with-api.c
+3 -1
@@ -89,7 +89,7 @@ static const char *curl_add_json_room(BUFFER *wb, const char *start, const char
89 size_t len = end - start;
90
91 // copy the item to an new buffer and terminate it
92 - char buf[len + 1];
92 + char *buf = mallocz(len + 1);
93 memcpy(buf, start, len);
94 buf[len] = '\0';
95
@@ -98,6 +98,8 @@ static const char *curl_add_json_room(BUFFER *wb, const char *start, const char
98 if(trimmed)
99 buffer_json_add_array_item_string(wb, trimmed);
100
101 + freez(buf);
102 +
103 if (last_item)
104 return NULL;
105
src/daemon/buildinfo.c
+2 -2
@@ -1113,7 +1113,7 @@ static void build_info_set_value(BUILD_INFO_SLOT slot, const char *value) {
1113 static void build_info_append_value(BUILD_INFO_SLOT slot, const char *value) {
1114 size_t size = BUILD_INFO[slot].value ? strlen(BUILD_INFO[slot].value) + 1 : 0;
1115 size += strlen(value);
1116 - char buf[size + 1];
1116 + CLEAN_CHAR_P *buf = mallocz(size + 1);
1117
1118 if(BUILD_INFO[slot].value) {
1119 strcpy(buf, BUILD_INFO[slot].value);
@@ -1566,7 +1566,7 @@ static void print_build_info_category_to_console(BUILD_INFO_CATEGORY category, c
1566 int padding_length = 60 - strlen(k) - 1;
1567 if (padding_length < 0) padding_length = 0;
1568
1569 - char padding[padding_length + 1];
1569 + char padding[61];
1570 memset(padding, '_', padding_length);
1571 padding[padding_length] = '\0';
1572
src/daemon/daemon-shutdown.c
+3 -1
@@ -272,7 +272,7 @@ static void netdata_cleanup_and_exit(EXIT_REASON reason, bool abnormal, bool exi
272 rrdeng_flush_everything_and_wait(true, true, false);
273 watcher_step_complete(WATCHER_STEP_ID_WAIT_FOR_DBENGINE_COLLECTORS_TO_FINISH);
274
275 - ND_THREAD *th[nd_profile.storage_tiers];
275 + ND_THREAD **th = callocz(nd_profile.storage_tiers, sizeof(*th));
276 for (size_t tier = 0; tier < nd_profile.storage_tiers; tier++)
277 th[tier] = nd_thread_create("rrdeng-exit", NETDATA_THREAD_OPTION_DEFAULT, rrdeng_exit_background, multidb_ctx[tier]);
278
@@ -282,6 +282,8 @@ static void netdata_cleanup_and_exit(EXIT_REASON reason, bool abnormal, bool exi
282 for (size_t tier = 0; tier < nd_profile.storage_tiers; tier++)
283 nd_thread_join(th[tier]);
284
285 + freez(th);
286 +
287 dbengine_shutdown();
288 watcher_step_complete(WATCHER_STEP_ID_STOP_DBENGINE_TIERS);
289 }
src/daemon/dyncfg/dyncfg-echo.c
+12 -9
@@ -87,8 +87,9 @@ void dyncfg_echo(const DICTIONARY_ITEM *item, DYNCFG *df, const char *id __maybe
87 e->cmd = cmd;
88 e->cmd_str = strdupz(cmd_str);
89
90 - char buf[string_strlen(df->function) + strlen(e->cmd_str) + 20];
91 - snprintfz(buf, sizeof(buf), "%s %s", string2str(df->function), e->cmd_str);
90 + size_t buf_size = string_strlen(df->function) + strlen(e->cmd_str) + 20;
91 + CLEAN_CHAR_P *buf = mallocz(buf_size);
92 + snprintfz(buf, buf_size, "%s %s", string2str(df->function), e->cmd_str);
93
94 rrd_function_run(
95 host, e->wb, 10,
@@ -120,8 +121,9 @@ void dyncfg_echo_update(const DICTIONARY_ITEM *item, DYNCFG *df, const char *id)
121 e->cmd = DYNCFG_CMD_UPDATE;
122 e->cmd_str = strdupz("update");
123
123 - char buf[string_strlen(df->function) + strlen(e->cmd_str) + 20];
124 - snprintfz(buf, sizeof(buf), "%s %s", string2str(df->function), e->cmd_str);
124 + size_t buf_size = string_strlen(df->function) + strlen(e->cmd_str) + 20;
125 + CLEAN_CHAR_P *buf = mallocz(buf_size);
126 + snprintfz(buf, buf_size, "%s %s", string2str(df->function), e->cmd_str);
127
128 rrd_function_run(
129 host, e->wb, 10,
@@ -155,8 +157,9 @@ static void dyncfg_echo_payload_add(const DICTIONARY_ITEM *item_template __maybe
157 e->cmd = DYNCFG_CMD_ADD;
158 e->cmd_str = strdupz(cmd);
159
158 - char buf[string_strlen(df_template->function) + strlen(cmd) + 20];
159 - snprintfz(buf, sizeof(buf), "%s %s", string2str(df_template->function), cmd);
160 + size_t buf_size = string_strlen(df_template->function) + strlen(cmd) + 20;
161 + CLEAN_CHAR_P *buf = mallocz(buf_size);
162 + snprintfz(buf, buf_size, "%s %s", string2str(df_template->function), cmd);
163
164 rrd_function_run(
165 host, e->wb, 10,
@@ -168,8 +171,8 @@ static void dyncfg_echo_payload_add(const DICTIONARY_ITEM *item_template __maybe
171 }
172
173 void dyncfg_echo_add(const DICTIONARY_ITEM *item_template, const DICTIONARY_ITEM *item_job, DYNCFG *df_template, DYNCFG *df_job, const char *template_id, const char *job_name) {
171 - char buf[strlen(job_name) + 20];
172 - snprintfz(buf, sizeof(buf), "add %s", job_name);
174 + size_t buf_size = strlen(job_name) + 20;
175 + CLEAN_CHAR_P *buf = mallocz(buf_size);
176 + snprintfz(buf, buf_size, "add %s", job_name);
177 dyncfg_echo_payload_add(item_template, item_job, df_template, df_job, template_id, buf);
178 }
175 -
src/daemon/dyncfg/dyncfg-intercept.c
+8 -9
@@ -110,8 +110,9 @@ static void dyncfg_log_user_action(DYNCFG *df, struct dyncfg_call *dc) {
110 // we intercept the config function calls of the plugin
111
112 static void dyncfg_function_intercept_job_successfully_added(DYNCFG *df_template, int code, struct dyncfg_call *dc) {
113 - char id[strlen(dc->id) + 1 + strlen(dc->add_name) + 1];
114 - snprintfz(id, sizeof(id), "%s:%s", dc->id, dc->add_name);
113 + size_t id_size = strlen(dc->id) + strlen(dc->add_name) + 2;
114 + CLEAN_CHAR_P *id = mallocz(id_size);
115 + snprintfz(id, id_size, "%s:%s", dc->id, dc->add_name);
116
117 RRDHOST *host = dyncfg_rrdhost(df_template);
118 if(!host) {
@@ -274,8 +275,7 @@ static int dyncfg_intercept_early_error(struct rrd_function_execute *rfe, int rc
275 }
276
277 const DICTIONARY_ITEM *dyncfg_get_template_of_new_job(const char *job_id) {
277 - char id_copy[strlen(job_id) + 1];
278 - memcpy(id_copy, job_id, sizeof(id_copy));
278 + CLEAN_CHAR_P *id_copy = strdupz(job_id);
279
280 char *colon = strrchr(id_copy, ':');
281 if(!colon) return NULL;
@@ -305,8 +305,7 @@ int dyncfg_function_intercept_cb(struct rrd_function_execute *rfe, void *data __
305 DYNCFG_CMDS cmd;
306 const DICTIONARY_ITEM *item = NULL;
307
308 - char buf[strlen(rfe->function) + 1];
309 - memcpy(buf, rfe->function, sizeof(buf));
308 + CLEAN_CHAR_P *buf = strdupz(rfe->function);
309
310 char *words[20];
311 size_t num_words = quoted_strings_splitter_whitespace(buf, words, 20);
@@ -346,8 +345,9 @@ int dyncfg_function_intercept_cb(struct rrd_function_execute *rfe, void *data __
345 "dyncfg functions intercept: this action requires a name");
346
347 if(!called_from_dyncfg_echo) {
349 - char nid[strlen(id) + strlen(add_name) + 2];
350 - snprintfz(nid, sizeof(nid), "%s:%s", id, add_name);
348 + size_t nid_size = strlen(id) + strlen(add_name) + 2;
349 + CLEAN_CHAR_P *nid = mallocz(nid_size);
350 + snprintfz(nid, nid_size, "%s:%s", id, add_name);
351
352 if (cmd == DYNCFG_CMD_ADD && dictionary_get(dyncfg_globals.nodes, nid))
353 return dyncfg_intercept_early_error(
@@ -538,4 +538,3 @@ int dyncfg_function_intercept_cb(struct rrd_function_execute *rfe, void *data __
538 dictionary_acquired_item_release(dyncfg_globals.nodes, item);
539 return rc;
540 }
541 -
src/daemon/dyncfg/dyncfg-tree.c
+4 -3
@@ -64,7 +64,7 @@ static void dyncfg_to_json(DYNCFG *df, const char *id, BUFFER *wb, bool anonymou
64 static void dyncfg_tree_for_host(RRDHOST *host, BUFFER *wb, const char *path, const char *id, bool anonymous) {
65 size_t entries = dictionary_entries(dyncfg_globals.nodes);
66 size_t used = 0;
67 - const DICTIONARY_ITEM *items[entries];
67 + const DICTIONARY_ITEM **items = entries ? callocz(entries, sizeof(*items)) : NULL;
68 size_t restart_required = 0, plugin_rejected = 0, status_incomplete = 0, status_failed = 0;
69
70 STRING *template = NULL;
@@ -150,14 +150,15 @@ static void dyncfg_tree_for_host(RRDHOST *host, BUFFER *wb, const char *path, co
150
151 for(size_t i = 0; i < used ;i++)
152 dictionary_acquired_item_release(dyncfg_globals.nodes, items[i]);
153 +
154 + freez(items);
155 }
156
157 static int dyncfg_config_execute_cb(struct rrd_function_execute *rfe, void *data) {
158 RRDHOST *host = data;
159 int code;
160
159 - char buf[strlen(rfe->function) + 1];
160 - memcpy(buf, rfe->function, sizeof(buf));
161 + CLEAN_CHAR_P *buf = strdupz(rfe->function);
162
163 char *words[MAX_FUNCTION_PARAMETERS]; // an array of pointers for the words in this line
164 size_t num_words = quoted_strings_splitter_whitespace(buf, words, MAX_FUNCTION_PARAMETERS);
src/daemon/dyncfg/dyncfg-unittest.c
+8 -8
@@ -89,8 +89,9 @@ bool dyncfg_unittest_parse_payload(BUFFER *payload, TEST *t, DYNCFG_CMDS cmd, co
89 t->current.value.bln = value_boolean;
90 }
91 else if(cmd == DYNCFG_CMD_ADD) {
92 - char buf[strlen(t->id) + strlen(add_name) + 20];
93 - snprintfz(buf, sizeof(buf), "%s:%s", t->id, add_name);
92 + size_t buf_size = strlen(t->id) + strlen(add_name) + 20;
93 + CLEAN_CHAR_P *buf = mallocz(buf_size);
94 + snprintfz(buf, buf_size, "%s:%s", t->id, add_name);
95 TEST tmp = {
96 .id = strdupz(buf),
97 .source = strdupz(source),
@@ -189,8 +190,7 @@ static int dyncfg_unittest_execute_cb(struct rrd_function_execute *rfe, void *da
190
191 t->received = true;
192
192 - char buf[strlen(rfe->function) + 1];
193 - memcpy(buf, rfe->function, sizeof(buf));
193 + CLEAN_CHAR_P *buf = strdupz(rfe->function);
194
195 char *words[MAX_FUNCTION_PARAMETERS]; // an array of pointers for the words in this line
196 size_t num_words = quoted_strings_splitter_whitespace(buf, words, MAX_FUNCTION_PARAMETERS);
@@ -420,8 +420,7 @@ void should_be_saved(TEST *t, DYNCFG_CMDS c) {
420 static int dyncfg_unittest_run(const char *cmd, BUFFER *wb, const char *payload, const char *source) {
421 dyncfg_unittest_reset();
422
423 - char buf[strlen(cmd) + 1];
424 - memcpy(buf, cmd, sizeof(buf));
423 + CLEAN_CHAR_P *buf = strdupz(cmd);
424
425 char *words[MAX_FUNCTION_PARAMETERS]; // an array of pointers for the words in this line
426 size_t num_words = quoted_strings_splitter_whitespace(buf, words, MAX_FUNCTION_PARAMETERS);
@@ -481,8 +480,9 @@ static int dyncfg_unittest_run(const char *cmd, BUFFER *wb, const char *payload,
480
481 if(rc == HTTP_RESP_OK && t->type == DYNCFG_TYPE_TEMPLATE) {
482 if(c == DYNCFG_CMD_ADD) {
484 - char buf2[strlen(id) + strlen(add_name) + 2];
485 - snprintfz(buf2, sizeof(buf2), "%s:%s", id, add_name);
483 + size_t buf2_size = strlen(id) + strlen(add_name) + 2;
484 + CLEAN_CHAR_P *buf2 = mallocz(buf2_size);
485 + snprintfz(buf2, buf2_size, "%s:%s", id, add_name);
486 TEST *tt = dictionary_get(dyncfg_unittest_data.nodes, buf2);
487 if (!tt) {
488 nd_log(NDLS_DAEMON, NDLP_ERR,
src/daemon/dyncfg/dyncfg.c
+4 -5
@@ -60,8 +60,9 @@ static void dyncfg_insert_cb(const DICTIONARY_ITEM *item, void *value, void *dat
60 dyncfg_normalize(df);
61
62 const char *id = dictionary_acquired_item_name(item);
63 - char buf[strlen(id) + 20];
64 - snprintfz(buf, sizeof(buf), PLUGINSD_FUNCTION_CONFIG " %s", id);
63 + size_t buf_size = strlen(id) + 20;
64 + CLEAN_CHAR_P *buf = mallocz(buf_size);
65 + snprintfz(buf, buf_size, PLUGINSD_FUNCTION_CONFIG " %s", id);
66 df->function = string_strdupz(buf);
67
68 if(df->type == DYNCFG_TYPE_JOB && !df->template) {
@@ -285,8 +286,7 @@ bool dyncfg_is_user_disabled(const char *id) {
286 }
287
288 bool dyncfg_job_has_registered_template(const char *id) {
288 - char buf[strlen(id) + 1];
289 - memcpy(buf, id, sizeof(buf));
289 + CLEAN_CHAR_P *buf = strdupz(id);
290 char *colon = strrchr(buf, ':');
291 if(!colon)
292 return false;
@@ -474,4 +474,3 @@ bool dyncfg_available_for_rrdhost(RRDHOST *host) {
474 }
475
476 // ----------------------------------------------------------------------------
477 -
src/daemon/main.c
+2 -2
@@ -289,7 +289,7 @@ int netdata_main(int argc, char **argv) {
289 // parse options
290 {
291 int num_opts = sizeof(option_definitions) / sizeof(struct option_def);
292 - char optstring[(num_opts * 2) + 1];
292 + char optstring[(sizeof(option_definitions) / sizeof(option_definitions[0]) * 2) + 1];
293
294 int string_i = 0;
295 for( i = 0; i < num_opts; i++ ) {
@@ -667,7 +667,7 @@ int netdata_main(int argc, char **argv) {
667 const char *haystack = argv[optind];
668 const char *needle = argv[optind + 1];
669 size_t len = strlen(needle) + 1;
670 - char wildcarded[len];
670 + CLEAN_CHAR_P *wildcarded = mallocz(len);
671
672 SIMPLE_PATTERN *p = simple_pattern_create(haystack, NULL, SIMPLE_PATTERN_EXACT, true);
673 SIMPLE_PATTERN_RESULT ret = simple_pattern_matches_extract(p, needle, wildcarded, len);
src/daemon/pulse/pulse-workers.c
+2 -2
@@ -752,7 +752,7 @@ static void workers_utilization_update_chart(struct worker_utilization *wu) {
752 size_t job_name_len = string_strlen(wu->per_job_type[i].name);
753 if(job_name_len > RRD_ID_LENGTH_MAX) job_name_len = RRD_ID_LENGTH_MAX;
754
755 - char job_name_sanitized[job_name_len + 1];
755 + char job_name_sanitized[RRD_ID_LENGTH_MAX + 1];
756 rrdset_strncpyz_name(job_name_sanitized, string2str(wu->per_job_type[i].name), job_name_len);
757
758 char name[RRD_ID_LENGTH_MAX + 1];
@@ -808,7 +808,7 @@ static void workers_utilization_update_chart(struct worker_utilization *wu) {
808 size_t job_name_len = string_strlen(wu->per_job_type[i].name);
809 if(job_name_len > RRD_ID_LENGTH_MAX) job_name_len = RRD_ID_LENGTH_MAX;
810
811 - char job_name_sanitized[job_name_len + 1];
811 + char job_name_sanitized[RRD_ID_LENGTH_MAX + 1];
812 rrdset_strncpyz_name(job_name_sanitized, string2str(wu->per_job_type[i].name), job_name_len);
813
814 char name[RRD_ID_LENGTH_MAX + 1];
src/daemon/status-file-dmi.c
+4 -3
@@ -124,14 +124,15 @@ static void linux_get_dmi_field(const char *field, const char *alt, char *dst, s
124 if (!filename[0])
125 return;
126
127 - char buf[MAX(256, dst_size)];
128 - if (read_txt_file(filename, buf, sizeof(buf)) != 0)
127 + size_t buf_size = MAX(256, dst_size);
128 + CLEAN_CHAR_P *buf = mallocz(buf_size);
129 + if (read_txt_file(filename, buf, buf_size) != 0)
130 return;
131
132 if (!buf[0])
133 return;
134
134 - dmi_clean_field(buf, sizeof(buf));
135 + dmi_clean_field(buf, buf_size);
136
137 if (!buf[0])
138 return;
src/libnetdata/json/json-c-parser-inline.h
+8 -5
@@ -525,11 +525,14 @@
525 } \
526 } \
527 else { \
528 - char _new_path[strlen(path) + strlen(member) + 2]; \
529 - snprintfz(_new_path, sizeof(_new_path), "%s%s%s", path, *path?".":"", member); \
528 + size_t _new_path_size = strlen(path) + strlen(member) + 2; \
529 + char *_new_path = mallocz(_new_path_size); \
530 + snprintfz(_new_path, _new_path_size, "%s%s%s", path, *path?".":"", member); \
531 if (!callback(_j, _new_path, dst, error, flags)) { \
532 + freez(_new_path); \
533 return false; \
534 } \
535 + freez(_new_path); \
536 } \
537 } else if((flags) & JSONC_REQUIRED) { \
538 buffer_sprintf(error, "missing '%s.%s' object", path, member); \
@@ -587,7 +590,7 @@
590 else { \
591 json_object *JSONC_TEMP_VAR(saved_jobj, __LINE__) = jobj; \
592 jobj = JSONC_TEMP_VAR(_j, __LINE__); \
590 - char JSONC_TEMP_VAR(saved_path, __LINE__)[strlen(path) + 1]; \
593 + char JSONC_TEMP_VAR(saved_path, __LINE__)[sizeof(path)]; \
594 strncpyz(JSONC_TEMP_VAR(saved_path, __LINE__), path, sizeof(JSONC_TEMP_VAR(saved_path, __LINE__))); \
595 JSONC_PATH_CONCAT(path, sizeof(path), path, member, error); \
596 /* Run the user's code block */ \
@@ -618,7 +621,7 @@
621 else { \
622 json_object *JSONC_TEMP_VAR(saved_jobj, __LINE__) = jobj; \
623 jobj = JSONC_TEMP_VAR(_jarray, __LINE__); \
621 - char JSONC_TEMP_VAR(saved_path, __LINE__)[strlen(path) + 1]; \
624 + char JSONC_TEMP_VAR(saved_path, __LINE__)[sizeof(path)]; \
625 strncpyz(JSONC_TEMP_VAR(saved_path, __LINE__), path, sizeof(JSONC_TEMP_VAR(saved_path, __LINE__))); \
626 JSONC_PATH_CONCAT(path, sizeof(path), path, member, error); \
627 /* Run the user's code block */ \
@@ -643,7 +646,7 @@
646 else { \
647 json_object *JSONC_TEMP_VAR(saved_jobj, __LINE__) = jobj; \
648 jobj = JSONC_TEMP_VAR(_jitem, __LINE__); \
646 - char JSONC_TEMP_VAR(saved_path, __LINE__)[strlen(path) + 1]; \
649 + char JSONC_TEMP_VAR(saved_path, __LINE__)[sizeof(path)]; \
650 strncpyz(JSONC_TEMP_VAR(saved_path, __LINE__), path, sizeof(JSONC_TEMP_VAR(saved_path, __LINE__))); \
651 JSONC_PATH_CONCAT_INDEX(path, sizeof(path), index, error); \
652 /* Run the user's code block */ \