Remove VLA (variable-length arrays) from collectors (#22066)
thiagoftsm committed
Mar 30, 2026 at 22:04 UTC
cff3aaef92e644bdf94b132064471f0f9a5336ea
12 files changed
+83
-45
src/collectors/apps.plugin/apps_os_windows.c
+7
-4
@@ -565,8 +565,7 @@ STRING *GetProcessFriendlyNameFromPathSanitized(WCHAR *path) {
565
static STRING *GetNameFromCmdlineSanitized(struct pid_stat *p) {
566
if(!p->cmdline) return NULL;
567
568
- char buf[string_strlen(p->cmdline) + 1];
569
- memcpy(buf, string2str(p->cmdline), sizeof(buf));
568
+ char *buf = strdupz(string2str(p->cmdline));
569
char *words[100];
570
size_t num_words = quoted_strings_splitter(buf, words, 100, isspace_map_pluginsd);
571
@@ -574,15 +573,19 @@ static STRING *GetNameFromCmdlineSanitized(struct pid_stat *p) {
573
// find -s SERVICE in the command line
574
for(size_t i = 0; i < num_words ;i++) {
575
if(strcmp(words[i], "-s") == 0 && i + 1 < num_words) {
577
- char service[strlen(words[i + 1]) + sizeof(SERVICE_PREFIX)]; // sizeof() includes a null
576
+ char *service = mallocz(strlen(words[i + 1]) + sizeof(SERVICE_PREFIX)); // sizeof() includes a null
577
strcpy(service, SERVICE_PREFIX);
578
strcpy(&service[sizeof(SERVICE_PREFIX) - 1], words[i + 1]);
579
sanitize_apps_plugin_chart_meta(service);
581
- return string_strdupz(service);
580
+ STRING *sanitized = string_strdupz(service);
581
+ freez(service);
582
+ freez(buf);
583
+ return sanitized;
584
}
585
}
586
}
587
588
+ freez(buf);
589
return NULL;
590
}
591
src/collectors/apps.plugin/apps_pid.c
+15
-8
@@ -405,8 +405,7 @@ static void remove_extension(char *name) {
405
static inline STRING *comm_from_cmdline_param_sanitized(STRING *cmdline) {
406
if(!cmdline) return NULL;
407
408
- char buf[string_strlen(cmdline) + 1];
409
- memcpy(buf, string2str(cmdline), sizeof(buf));
408
+ char *buf = strdupz(string2str(cmdline));
409
410
char *words[100];
411
size_t num_words = quoted_strings_splitter_whitespace(buf, words, 100);
@@ -424,19 +423,21 @@ static inline STRING *comm_from_cmdline_param_sanitized(STRING *cmdline) {
423
name++;
424
remove_extension(name);
425
sanitize_apps_plugin_chart_meta(name);
427
- return string_strdupz(name);
426
+ STRING *sanitized = string_strdupz(name);
427
+ freez(buf);
428
+ return sanitized;
429
}
430
}
431
}
432
433
+ freez(buf);
434
return NULL;
435
}
436
437
static inline STRING *comm_from_cmdline_sanitized(STRING *comm, STRING *cmdline) {
438
if(!cmdline) return NULL;
439
438
- char buf[string_strlen(cmdline) + 1];
439
- memcpy(buf, string2str(cmdline), sizeof(buf));
440
+ char *buf = strdupz(string2str(cmdline));
441
442
size_t comm_len = string_strlen(comm);
443
char *start = strstr(buf, string2str(comm));
@@ -456,9 +457,12 @@ static inline STRING *comm_from_cmdline_sanitized(STRING *comm, STRING *cmdline)
457
458
remove_extension(start);
459
sanitize_apps_plugin_chart_meta(start);
459
- return string_strdupz(start);
460
+ STRING *sanitized = string_strdupz(start);
461
+ freez(buf);
462
+ return sanitized;
463
}
464
465
+ freez(buf);
466
return NULL;
467
}
468
@@ -505,16 +509,19 @@ void update_pid_comm(struct pid_stat *p, const char *comm) {
509
510
// some process names have ( and ), remove the parenthesis
511
size_t len = strlen(comm);
508
- char buf[len + 1];
512
+ char *buf;
513
if(comm[0] == '(' && comm[len - 1] == ')') {
514
+ buf = mallocz(len - 1);
515
memcpy(buf, &comm[1], len - 2);
516
buf[len - 2] = '\0';
517
}
518
else
514
- memcpy(buf, comm, sizeof(buf));
519
+ buf = strdupz(comm);
520
521
sanitize_apps_plugin_chart_meta(buf);
522
+ string_freez(p->comm);
523
p->comm = string_strdupz(buf);
524
+ freez(buf);
525
p->is_manager = is_process_a_manager(p);
526
p->is_aggregator = is_process_an_aggregator(p);
527
src/collectors/apps.plugin/apps_pid_match.c
+4
-5
@@ -102,13 +102,12 @@ APPS_MATCH pid_match_create(const char *comm) {
102
};
103
104
// copy comm to make changes to it
105
- size_t len = strlen(comm);
106
- char buf[len + 1];
107
- memcpy(buf, comm, sizeof(buf));
105
+ char *buf = strdupz(comm);
106
107
trim_all(buf);
108
+ size_t len = strlen(buf);
109
111
- if(buf[len - 1] == '*') {
110
+ if(len && buf[len - 1] == '*') {
111
buf[--len] = '\0';
112
m.starts_with = true;
113
}
@@ -124,6 +123,7 @@ APPS_MATCH pid_match_create(const char *comm) {
123
if(strchr(nid, '*'))
124
m.pattern = simple_pattern_create(comm, SIMPLE_PATTERN_NO_SEPARATORS, SIMPLE_PATTERN_EXACT, false);
125
126
+ freez(buf);
127
return m;
128
}
129
@@ -131,4 +131,3 @@ void pid_match_cleanup(APPS_MATCH *m) {
131
string_freez(m->compare);
132
simple_pattern_free(m->pattern);
133
}
134
-
src/collectors/apps.plugin/apps_targets.c
+4
-3
@@ -5,14 +5,15 @@
5
pid_t INIT_PID = OS_INIT_PID;
6
7
static STRING *get_clean_name(STRING *name) {
8
- char buf[string_strlen(name) + 1];
9
- memcpy(buf, string2str(name), string_strlen(name) + 1);
8
+ char *buf = strdupz(string2str(name));
9
netdata_fix_chart_name(buf);
10
11
for (char *d = buf; *d ; d++)
12
if (*d == '.') *d = '_';
13
15
- return string_strdupz(buf);
14
+ STRING *clean = string_strdupz(buf);
15
+ freez(buf);
16
+ return clean;
17
}
18
19
static inline STRING *get_numeric_string(uint64_t n) {
src/collectors/ebpf.plugin/libbpf_api/ebpf_library.c
+6
-2
@@ -1432,8 +1432,7 @@ static void ebpf_parse_service_list(void **out, const char *service)
1432
*/
1433
static void ebpf_parse_port_list(void **out, const char *range_param)
1434
{
1435
- char range[strlen(range_param) + 1];
1436
- strncpyz(range, range_param, strlen(range_param));
1435
+ char *range = strdupz(range_param);
1436
1437
int first, last;
1438
ebpf_network_viewer_port_list_t **list = (ebpf_network_viewer_port_list_t **)out;
@@ -1459,6 +1458,7 @@ static void ebpf_parse_port_list(void **out, const char *range_param)
1458
netdata_log_info(
1459
"The exclusion cannot be in the second part of the range, the range %s will be ignored.", copied);
1460
freez(copied);
1461
+ freez(range);
1462
return;
1463
}
1464
last = str2i((const char *)end);
@@ -1470,6 +1470,7 @@ static void ebpf_parse_port_list(void **out, const char *range_param)
1470
if (first < NETDATA_MINIMUM_PORT_VALUE || first > NETDATA_MAXIMUM_PORT_VALUE) {
1471
netdata_log_info("The first port %d of the range \"%s\" is invalid and it will be ignored!", first, copied);
1472
freez(copied);
1473
+ freez(range);
1474
return;
1475
}
1476
@@ -1480,6 +1481,7 @@ static void ebpf_parse_port_list(void **out, const char *range_param)
1481
netdata_log_info(
1482
"The second port %d of the range \"%s\" is invalid and the whole range will be ignored!", last, copied);
1483
freez(copied);
1484
+ freez(range);
1485
return;
1486
}
1487
@@ -1487,6 +1489,7 @@ static void ebpf_parse_port_list(void **out, const char *range_param)
1489
netdata_log_info(
1490
"The specified order %s is wrong, the smallest value is always the first, it will be ignored!", copied);
1491
freez(copied);
1492
+ freez(range);
1493
return;
1494
}
1495
@@ -1501,6 +1504,7 @@ fillenvpl:
1504
w->cmp_last = (uint16_t)last;
1505
1506
fill_port_list(list, w);
1507
+ freez(range);
1508
}
1509
1510
/**
src/collectors/freeipmi.plugin/freeipmi_plugin.c
+4
-2
@@ -1488,8 +1488,7 @@ static void freeimi_function_sensors(const char *transaction, char *function __m
1488
buffer_json_member_add_boolean(wb, "has_history", false);
1489
buffer_json_member_add_string(wb, "help", "View IPMI sensor readings and its state");
1490
1491
- char function_copy[strlen(function) + 1];
1492
- memcpy(function_copy, function, sizeof(function_copy));
1491
+ char *function_copy = strdupz(function);
1492
char *words[1024];
1493
size_t num_words = quoted_strings_splitter_whitespace(function_copy, words, 1024);
1494
for(size_t i = 1; i < num_words ;i++) {
@@ -1499,10 +1498,13 @@ static void freeimi_function_sensors(const char *transaction, char *function __m
1498
buffer_json_array_close(wb); // accepted_params
1499
buffer_json_member_add_array(wb, "required_params");
1500
buffer_json_array_close(wb); // required_params
1501
+ freez(function_copy);
1502
goto close_and_send;
1503
}
1504
}
1505
1506
+ freez(function_copy);
1507
+
1508
buffer_json_member_add_array(wb, "data");
1509
1510
struct sensor *sn;
src/collectors/log2journal/log2journal-yaml.c
+3
-2
@@ -217,13 +217,14 @@ static void yaml_print_multiline_value(const char *s, size_t depth) {
217
if(next) next++;
218
219
size_t len = next ? (size_t)(next - s) : strlen(s);
220
- char buf[len + 1];
221
- copy_to_buffer(buf, sizeof(buf), s, len);
220
+ char *buf = mallocz(len + 1);
221
+ copy_to_buffer(buf, len + 1, s, len);
222
223
fprintf(stderr, "%.*s%s%s",
224
(int)(depth * 2), " ",
225
buf, next ? "" : "\n");
226
227
+ freez(buf);
228
s = next;
229
} while(s && *s);
230
}
src/collectors/network-viewer.plugin/network-viewer.c
+4
-2
@@ -470,8 +470,7 @@ void network_viewer_function(const char *transaction, char *function __maybe_unu
470
buffer_json_array_close(wb); // required_params
471
#endif
472
473
- char function_copy[strlen(function) + 1];
474
- memcpy(function_copy, function, sizeof(function_copy));
473
+ char *function_copy = strdupz(function);
474
char *words[1024];
475
size_t num_words = quoted_strings_splitter_whitespace(function_copy, words, 1024);
476
for(size_t i = 1; i < num_words ;i++) {
@@ -483,10 +482,13 @@ void network_viewer_function(const char *transaction, char *function __maybe_unu
482
aggregated = false;
483
}
484
else if(strcmp(param, "info") == 0) {
485
+ freez(function_copy);
486
goto close_and_send;
487
}
488
}
489
490
+ freez(function_copy);
491
+
492
if(aggregated) {
493
buffer_json_member_add_object(wb, "aggregated_view");
494
{
src/collectors/statsd.plugin/statsd.c
+9
-3
@@ -1551,7 +1551,8 @@ static inline void statsd_get_metric_type_and_id(STATSD_METRIC *m, char *type, c
1551
// ${STATSD_CHART_PREFIX} + "_" + the first word of ${METRIC_NAME}
1552
1553
// find the first word of ${METRIC_NAME}
1554
- char firstword[len + 1], *s = "";
1554
+ char *firstword = mallocz(len + 1);
1555
+ char *s = "";
1556
strncpyz(firstword, m->name, len);
1557
for (s = firstword; *s ; s++) {
1558
if (unlikely(*s == '.' || *s == '_')) {
@@ -1574,6 +1575,8 @@ static inline void statsd_get_metric_type_and_id(STATSD_METRIC *m, char *type, c
1575
else
1576
snprintfz(id, len, "%s", metrictype);
1577
1578
+ freez(firstword);
1579
+
1580
// for the context, we want the full of both the above, separated with a dot (type.id):
1581
snprintfz(context, RRD_ID_LENGTH_MAX, "%s.%s", type, id);
1582
@@ -2136,7 +2139,7 @@ static inline void check_if_metric_is_for_app(STATSD_INDEX *index, STATSD_METRIC
2139
if(unlikely(dim->metric_pattern)) {
2140
size_t dim_name_len = strlen(dim->name);
2141
size_t wildcarded_len = dim_name_len + strlen(m->name) + 1;
2139
- char wildcarded[wildcarded_len];
2142
+ char *wildcarded = mallocz(wildcarded_len);
2143
2144
strcpy(wildcarded, dim->name);
2145
char *ws = &wildcarded[dim_name_len];
@@ -2175,6 +2178,8 @@ static inline void check_if_metric_is_for_app(STATSD_INDEX *index, STATSD_METRIC
2178
// the new dimension is appended to the list
2179
// so, it will be matched and linked later too
2180
}
2181
+
2182
+ freez(wildcarded);
2183
}
2184
else if(!dim->value_ptr && dim->metric_hash == m->hash && !strcmp(dim->metric, m->name)) {
2185
// we have a match - this metric should be linked to this dimension
@@ -2212,7 +2217,7 @@ static inline RRDDIM *statsd_add_dim_to_app_chart(STATSD_APP *app, STATSD_APP_CH
2217
// the same metric is found multiple times
2218
2219
size_t len = strlen(dim->metric) + 100;
2215
- char metric[ len + 1 ];
2220
+ char *metric = mallocz(len + 1);
2221
2222
if(count_same_metric_value_type > 1) {
2223
// the same metric, with the same value type, is added multiple times
@@ -2224,6 +2229,7 @@ static inline RRDDIM *statsd_add_dim_to_app_chart(STATSD_APP *app, STATSD_APP_CH
2229
}
2230
2231
dim->rd = rrddim_add(chart->st, metric, dim->name, dim->multiplier, dim->divisor, dim->algorithm);
2232
+ freez(metric);
2233
if(dim->flags != RRDDIM_FLAG_NONE) dim->rd->flags |= dim->flags;
2234
if(dim->options != RRDDIM_OPTION_NONE) dim->rd->collector.options |= dim->options;
2235
return dim->rd;
src/collectors/systemd-journal.plugin/systemd-journal-files.c
+17
-9
@@ -313,29 +313,35 @@ void nd_journal_file_update_header(const char *filename, struct nd_journal_file
313
314
static STRING *string_strdupz_source(const char *s, const char *e, size_t max_len, const char *prefix)
315
{
316
- char buf[max_len];
316
+ size_t buf_size = max_len;
317
+ size_t remaining = max_len;
318
+ char *buf = mallocz(buf_size);
319
size_t len;
320
char *dst = buf;
321
322
if (prefix) {
323
len = strlen(prefix);
324
+ if (len >= remaining)
325
+ len = remaining - 1;
326
memcpy(buf, prefix, len);
327
dst = &buf[len];
324
- max_len -= len;
328
+ remaining -= len;
329
}
330
331
len = e - s;
328
- if (len >= max_len)
329
- len = max_len - 1;
332
+ if (len >= remaining)
333
+ len = remaining - 1;
334
memcpy(dst, s, len);
335
dst[len] = '\0';
332
- buf[max_len - 1] = '\0';
336
+ buf[buf_size - 1] = '\0';
337
338
for (size_t i = 0; buf[i]; i++)
339
if (!is_netdata_api_valid_character(buf[i]))
340
buf[i] = '_';
341
338
- return string_strdupz(buf);
342
+ STRING *copy = string_strdupz(buf);
343
+ freez(buf);
344
+ return copy;
345
}
346
347
static void files_registry_insert_cb(const DICTIONARY_ITEM *item, void *value, void *data __maybe_unused)
@@ -365,9 +371,10 @@ static void files_registry_insert_cb(const DICTIONARY_ITEM *item, void *value, v
371
;
372
if (d == e) {
373
// a valid IP address
368
- char ip[e - s + 1];
369
- memcpy(ip, s, e - s);
370
- ip[e - s] = '\0';
374
+ size_t ip_len = (size_t)(e - s);
375
+ char *ip = mallocz(ip_len + 1);
376
+ memcpy(ip, s, ip_len);
377
+ ip[ip_len] = '\0';
378
char buf[ND_SD_JOURNAL_MAX_SOURCE_LEN];
379
if (ip_to_hostname(ip, buf, sizeof(buf)))
380
njf->source =
@@ -376,6 +383,7 @@ static void files_registry_insert_cb(const DICTIONARY_ITEM *item, void *value, v
383
internal_error(true, "Cannot find the hostname for IP '%s'", ip);
384
njf->source = string_strdupz_source(s, e, ND_SD_JOURNAL_MAX_SOURCE_LEN, "remote-");
385
}
386
+ freez(ip);
387
} else
388
njf->source = string_strdupz_source(s, e, ND_SD_JOURNAL_MAX_SOURCE_LEN, "remote-");
389
}
src/collectors/windows-events.plugin/windows-events-sources.c
+6
-3
@@ -581,18 +581,21 @@ void wevt_sources_scan(void) {
581
provider = "Netdata";
582
583
if(provider && *provider) {
584
- char buf[sizeof(WEVT_SOURCE_ALL_OF_PROVIDER_PREFIX) + strlen(provider)]; // sizeof() includes terminator
585
- snprintf(buf, sizeof(buf), WEVT_SOURCE_ALL_OF_PROVIDER_PREFIX "%s", provider);
584
+ size_t buf_size = sizeof(WEVT_SOURCE_ALL_OF_PROVIDER_PREFIX) + strlen(provider); // sizeof() includes terminator
585
+ char *buf = mallocz(buf_size);
586
+ snprintf(buf, buf_size, WEVT_SOURCE_ALL_OF_PROVIDER_PREFIX "%s", provider);
587
588
trim_all(buf);
589
if(buf[0]) {
589
- for (size_t i = 0; i < sizeof(buf) - 1 && buf[i]; i++) {
590
+ for (size_t i = 0; i < buf_size - 1 && buf[i]; i++) {
591
// remove character that may interfere with our parsing
592
if (isspace((uint8_t) buf[i]) || buf[i] == '%' || buf[i] == '+' || buf[i] == '|' || buf[i] == ':')
593
buf[i] = '_';
594
}
595
src.provider = string_strdupz(buf);
596
}
597
+
598
+ freez(buf);
599
}
600
601
dictionary_set(wevt_sources, src.fullname, &src, sizeof(src));
src/collectors/windows-events.plugin/windows-events-xml.c
+4
-2
@@ -233,12 +233,13 @@ bool buffer_extract_and_print_xml_with_cb(BUFFER *buffer, const char *xml, size_
233
if(!*keys[k]) continue;
234
235
size_t klen = strlen(keys[k]);
236
- char tag_open[klen + 2];
236
+ char *tag_open = mallocz(klen + 2);
237
tag_open[0] = '<';
238
strcpy(&tag_open[1], keys[k]);
239
tag_open[klen + 1] = '\0';
240
241
const char *new_start = strstr(start, tag_open);
242
+ freez(tag_open);
243
if(!new_start)
244
return false;
245
@@ -253,7 +254,7 @@ bool buffer_extract_and_print_xml_with_cb(BUFFER *buffer, const char *xml, size_
254
}
255
start++; // skip the >
256
256
- char tag_close[klen + 4];
257
+ char *tag_close = mallocz(klen + 4);
258
tag_close[0] = '<';
259
tag_close[1] = '/';
260
strcpy(&tag_close[2], keys[k]);
@@ -261,6 +262,7 @@ bool buffer_extract_and_print_xml_with_cb(BUFFER *buffer, const char *xml, size_
262
tag_close[klen + 3] = '\0';
263
264
const char *new_end = strstr(start, tag_close);
265
+ freez(tag_close);
266
if(!new_end || (end && new_end > end))
267
return false;
268