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 */ \