UTF8 support for chart ids, names and other metadata (#18684)
* eval without hardcoding what variables look like * allow international characters in journal sources * removed left-over sanitizers from health config * international characters support for chart ids and names * renamed for clarity
Costa Tsaousis committed
Oct 4, 2024 at 17:58 UTC
7da20f8a2a1c2289eea3219b3c22f95539f7e96e
10 files changed
+211
-602
src/collectors/systemd-journal.plugin/systemd-journal-files.c
+1
-2
@@ -369,8 +369,7 @@ static STRING *string_strdupz_source(const char *s, const char *e, size_t max_le
369
buf[max_len - 1] = '\0';
370
371
for(size_t i = 0; buf[i] ;i++)
372
- if(!isalnum(buf[i]) && buf[i] != '-' && buf[i] != '.' && buf[i] != ':')
373
- buf[i] = '_';
372
+ if(!is_netdata_api_valid_character(buf[i])) buf[i] = '_';
373
374
return string_strdupz(buf);
375
}
src/database/rrd.h
-1
@@ -1569,7 +1569,6 @@ void rrddim_store_metric(RRDDIM *rd, usec_t point_end_time_ut, NETDATA_DOUBLE n,
1569
// ----------------------------------------------------------------------------
1570
// Miscellaneous functions
1571
1572
-char *rrdset_strncpyz_name(char *to, const char *from, size_t length);
1572
void reload_host_labels(void);
1573
void rrdhost_set_is_parent_label(void);
1574
src/database/rrdset.c
-15
@@ -597,21 +597,6 @@ void rrdset_acquired_release(RRDSET_ACQUIRED *rsa) {
597
// ----------------------------------------------------------------------------
598
// RRDSET - rename charts
599
600
-char *rrdset_strncpyz_name(char *to, const char *from, size_t length) {
601
- char c, *p = to;
602
-
603
- while (length-- && (c = *from++)) {
604
- if(c != '.' && c != '-' && !isalnum(c))
605
- c = '_';
606
-
607
- *p++ = c;
608
- }
609
-
610
- *p = '\0';
611
-
612
- return to;
613
-}
614
-
600
int rrdset_reset_name(RRDSET *st, const char *name) {
601
if(unlikely(!strcmp(rrdset_name(st), name)))
602
return 1;
src/health/health_config.c
-7
@@ -155,13 +155,6 @@ static inline int health_parse_repeat(
155
return 1;
156
}
157
158
-static inline int isvariableterm(const char s) {
159
- if(isalnum(s) || s == '.' || s == '_')
160
- return 0;
161
-
162
- return 1;
163
-}
164
-
158
static inline int health_parse_db_lookup(size_t line, const char *filename, char *string, struct rrd_alert_config *ac) {
159
if(ac->dimensions) string_freez(ac->dimensions);
160
ac->dimensions = NULL;
src/health/rrdvar.c
-14
@@ -9,20 +9,6 @@ typedef struct rrdvar {
9
// ----------------------------------------------------------------------------
10
// RRDVAR management
11
12
-inline int rrdvar_fix_name(char *variable) {
13
- int fixed = 0;
14
- while(*variable) {
15
- if (!isalnum((uint8_t)*variable) && *variable != '.' && *variable != '_') {
16
- *variable++ = '_';
17
- fixed++;
18
- }
19
- else
20
- variable++;
21
- }
22
-
23
- return fixed;
24
-}
25
-
12
inline STRING *rrdvar_name_to_string(const char *name) {
13
char *variable = strdupz(name);
14
rrdvar_fix_name(variable);
src/health/rrdvar.h
-2
@@ -7,8 +7,6 @@
7
8
#define RRDVAR_MAX_LENGTH 1024
9
10
-int rrdvar_fix_name(char *variable);
11
-
10
#include "database/rrd.h"
11
12
STRING *rrdvar_name_to_string(const char *name);
src/libnetdata/config/dyncfg.c
+2
-2
@@ -211,7 +211,7 @@ bool dyncfg_is_valid_id(const char *id) {
211
return true;
212
}
213
214
-static inline bool is_forbidden_char(char c) {
214
+static inline bool is_forbidden_filename_char(char c) {
215
if(isspace((uint8_t)c) || !isprint((uint8_t)c))
216
return true;
217
@@ -239,7 +239,7 @@ char *dyncfg_escape_id_for_filename(const char *id) {
239
char *dest = escaped;
240
241
while (*src) {
242
- if (is_forbidden_char(*src)) {
242
+ if (is_forbidden_filename_char(*src)) {
243
sprintf(dest, "%%%02X", (unsigned char)*src);
244
dest += 3;
245
} else {
src/libnetdata/eval/eval.c
+75
-39
@@ -387,29 +387,63 @@ static inline void skip_spaces(const char **string) {
387
*string = s;
388
}
389
390
-// what character can appear just after an operator keyword
391
-// like NOT AND OR ?
392
-static inline int isoperatorterm_word(const char s) {
393
- if(isspace(s) || s == '(' || s == '$' || s == '!' || s == '-' || s == '+' || isdigit(s) || !s)
394
- return 1;
395
-
396
- return 0;
390
+//static inline int old_isoperatorterm_word(const char s) {
391
+// if (isspace(s) || s == '(' || s == '$' || s == '!' || s == '-' || s == '+' || isdigit(s) || !s)
392
+// return 1;
393
+// return 0;
394
+//}
395
+//
396
+//static inline int old_isoperatorterm_symbol(const char s) {
397
+// if (old_isoperatorterm_word(s) || isalpha(s))
398
+// return 1;
399
+// return 0;
400
+//}
401
+//
402
+//// return 1 if the character should never appear in a variable
403
+//static inline int old_isvariableterm(const char s) {
404
+// if (isalnum(s) || s == '.' || s == '_')
405
+// return 0;
406
+// return 1;
407
+//}
408
+
409
+static inline bool is_operator_first_symbol_or_space(const char s) {
410
+ return (
411
+ isspace((uint8_t)s) || !s ||
412
+ s == '&' || s == '|' || s == '!' || s == '>' || s == '<' ||
413
+ s == '=' || s == '+' || s == '-' || s == '*' || s == '/' || s == '?');
414
+}
415
+
416
+// what character can appear just after the operators: NOT, AND, OR
417
+static inline bool is_valid_after_operator_word(const char s) {
418
+ bool rc = isspace((uint8_t)s) || s == '(' || s == '$' || s == '!' || s == '-' || s == '+' || isdigit((uint8_t)s) || !s;
419
+// bool old = old_isoperatorterm_word(s);
420
+// if(rc != old) {
421
+// int x = 0;
422
+// x++;
423
+// }
424
+ return rc;
425
}
426
427
// what character can appear just after an operator symbol?
400
-static inline int isoperatorterm_symbol(const char s) {
401
- if(isoperatorterm_word(s) || isalpha(s))
402
- return 1;
403
-
404
- return 0;
405
-}
406
-
407
-// return 1 if the character should never appear in a variable
408
-static inline int isvariableterm(const char s) {
409
- if(isalnum(s) || s == '.' || s == '_')
410
- return 0;
411
-
412
- return 1;
428
+static inline bool is_valid_after_operator_symbol(const char s) {
429
+ bool rc = is_valid_after_operator_word(s) || is_operator_first_symbol_or_space(s);
430
+// bool old = old_isoperatorterm_symbol(s);
431
+// if(rc != old) {
432
+// int x = 0;
433
+// x++;
434
+// }
435
+ return rc;
436
+}
437
+
438
+// return true if the character may appear in a variable name
439
+static inline bool is_valid_variable_character(const char s) {
440
+ bool rc = !is_operator_first_symbol_or_space(s) && s != ')' && s != '}';
441
+// bool old = !old_isvariableterm(s);
442
+// if(rc != old) {
443
+// int x = 0;
444
+// x++;
445
+// }
446
+ return rc;
447
}
448
449
// ----------------------------------------------------------------------------
@@ -419,13 +453,14 @@ static inline int parse_and(const char **string) {
453
const char *s = *string;
454
455
// AND
422
- if((s[0] == 'A' || s[0] == 'a') && (s[1] == 'N' || s[1] == 'n') && (s[2] == 'D' || s[2] == 'd') && isoperatorterm_word(s[3])) {
456
+ if((s[0] == 'A' || s[0] == 'a') && (s[1] == 'N' || s[1] == 'n') && (s[2] == 'D' || s[2] == 'd') &&
457
+ is_valid_after_operator_word(s[3])) {
458
*string = &s[4];
459
return 1;
460
}
461
462
// &&
428
- if(s[0] == '&' && s[1] == '&' && isoperatorterm_symbol(s[2])) {
463
+ if(s[0] == '&' && s[1] == '&' && is_valid_after_operator_symbol(s[2])) {
464
*string = &s[2];
465
return 1;
466
}
@@ -437,13 +472,13 @@ static inline int parse_or(const char **string) {
472
const char *s = *string;
473
474
// OR
440
- if((s[0] == 'O' || s[0] == 'o') && (s[1] == 'R' || s[1] == 'r') && isoperatorterm_word(s[2])) {
475
+ if((s[0] == 'O' || s[0] == 'o') && (s[1] == 'R' || s[1] == 'r') && is_valid_after_operator_word(s[2])) {
476
*string = &s[3];
477
return 1;
478
}
479
480
// ||
446
- if(s[0] == '|' && s[1] == '|' && isoperatorterm_symbol(s[2])) {
481
+ if(s[0] == '|' && s[1] == '|' && is_valid_after_operator_symbol(s[2])) {
482
*string = &s[2];
483
return 1;
484
}
@@ -455,7 +490,7 @@ static inline int parse_greater_than_or_equal(const char **string) {
490
const char *s = *string;
491
492
// >=
458
- if(s[0] == '>' && s[1] == '=' && isoperatorterm_symbol(s[2])) {
493
+ if(s[0] == '>' && s[1] == '=' && is_valid_after_operator_symbol(s[2])) {
494
*string = &s[2];
495
return 1;
496
}
@@ -467,7 +502,7 @@ static inline int parse_less_than_or_equal(const char **string) {
502
const char *s = *string;
503
504
// <=
470
- if (s[0] == '<' && s[1] == '=' && isoperatorterm_symbol(s[2])) {
505
+ if (s[0] == '<' && s[1] == '=' && is_valid_after_operator_symbol(s[2])) {
506
*string = &s[2];
507
return 1;
508
}
@@ -479,7 +514,7 @@ static inline int parse_greater(const char **string) {
514
const char *s = *string;
515
516
// >
482
- if(s[0] == '>' && isoperatorterm_symbol(s[1])) {
517
+ if(s[0] == '>' && is_valid_after_operator_symbol(s[1])) {
518
*string = &s[1];
519
return 1;
520
}
@@ -491,7 +526,7 @@ static inline int parse_less(const char **string) {
526
const char *s = *string;
527
528
// <
494
- if(s[0] == '<' && isoperatorterm_symbol(s[1])) {
529
+ if(s[0] == '<' && is_valid_after_operator_symbol(s[1])) {
530
*string = &s[1];
531
return 1;
532
}
@@ -503,13 +538,13 @@ static inline int parse_equal(const char **string) {
538
const char *s = *string;
539
540
// ==
506
- if(s[0] == '=' && s[1] == '=' && isoperatorterm_symbol(s[2])) {
541
+ if(s[0] == '=' && s[1] == '=' && is_valid_after_operator_symbol(s[2])) {
542
*string = &s[2];
543
return 1;
544
}
545
546
// =
512
- if(s[0] == '=' && isoperatorterm_symbol(s[1])) {
547
+ if(s[0] == '=' && is_valid_after_operator_symbol(s[1])) {
548
*string = &s[1];
549
return 1;
550
}
@@ -521,13 +556,13 @@ static inline int parse_not_equal(const char **string) {
556
const char *s = *string;
557
558
// !=
524
- if(s[0] == '!' && s[1] == '=' && isoperatorterm_symbol(s[2])) {
559
+ if(s[0] == '!' && s[1] == '=' && is_valid_after_operator_symbol(s[2])) {
560
*string = &s[2];
561
return 1;
562
}
563
564
// <>
530
- if(s[0] == '<' && s[1] == '>' && isoperatorterm_symbol(s[2])) {
565
+ if(s[0] == '<' && s[1] == '>' && is_valid_after_operator_symbol(s[2])) {
566
*string = &s[2];
567
}
568
@@ -538,7 +573,8 @@ static inline int parse_not(const char **string) {
573
const char *s = *string;
574
575
// NOT
541
- if((s[0] == 'N' || s[0] == 'n') && (s[1] == 'O' || s[1] == 'o') && (s[2] == 'T' || s[2] == 't') && isoperatorterm_word(s[3])) {
576
+ if((s[0] == 'N' || s[0] == 'n') && (s[1] == 'O' || s[1] == 'o') && (s[2] == 'T' || s[2] == 't') &&
577
+ is_valid_after_operator_word(s[3])) {
578
*string = &s[3];
579
return 1;
580
}
@@ -555,7 +591,7 @@ static inline int parse_multiply(const char **string) {
591
const char *s = *string;
592
593
// *
558
- if(s[0] == '*' && isoperatorterm_symbol(s[1])) {
594
+ if(s[0] == '*' && is_valid_after_operator_symbol(s[1])) {
595
*string = &s[1];
596
return 1;
597
}
@@ -567,7 +603,7 @@ static inline int parse_divide(const char **string) {
603
const char *s = *string;
604
605
// /
570
- if(s[0] == '/' && isoperatorterm_symbol(s[1])) {
606
+ if(s[0] == '/' && is_valid_after_operator_symbol(s[1])) {
607
*string = &s[1];
608
return 1;
609
}
@@ -579,7 +615,7 @@ static inline int parse_minus(const char **string) {
615
const char *s = *string;
616
617
// -
582
- if(s[0] == '-' && isoperatorterm_symbol(s[1])) {
618
+ if(s[0] == '-' && is_valid_after_operator_symbol(s[1])) {
619
*string = &s[1];
620
return 1;
621
}
@@ -591,7 +627,7 @@ static inline int parse_plus(const char **string) {
627
const char *s = *string;
628
629
// +
594
- if(s[0] == '+' && isoperatorterm_symbol(s[1])) {
630
+ if(s[0] == '+' && is_valid_after_operator_symbol(s[1])) {
631
*string = &s[1];
632
return 1;
633
}
@@ -646,7 +682,7 @@ static inline int parse_variable(const char **string, char *buffer, size_t len)
682
else {
683
// $variable_name
684
649
- while (*s && !isvariableterm(*s) && i < len)
685
+ while (*s && is_valid_variable_character(*s) && i < len)
686
buffer[i++] = *s++;
687
}
688
@@ -1219,7 +1255,7 @@ void expression_hardcode_variable(EVAL_EXPRESSION *expression, STRING *variable,
1255
}
1256
1257
if (s) {
1222
- if (s == s1 && (isalnum((uint8_t)s[len]) || s[len] == '_')) {
1258
+ if (s == s1 && !is_valid_variable_character(s[len])) {
1259
// Move past the variable if it's part of a larger word.
1260
source_ptr = s + len;
1261
continue;
src/libnetdata/sanitizers/chart_id_and_name.c
+126
-520
@@ -2,532 +2,138 @@
2
3
#include "../libnetdata.h"
4
5
-static uint8_t netdata_map_chart_names[256] = {
6
- [0] = '\0', //
7
- [1] = '_', //
8
- [2] = '_', //
9
- [3] = '_', //
10
- [4] = '_', //
11
- [5] = '_', //
12
- [6] = '_', //
13
- [7] = '_', //
14
- [8] = '_', //
15
- [9] = '_', //
16
- [10] = '_', //
17
- [11] = '_', //
18
- [12] = '_', //
19
- [13] = '_', //
20
- [14] = '_', //
21
- [15] = '_', //
22
- [16] = '_', //
23
- [17] = '_', //
24
- [18] = '_', //
25
- [19] = '_', //
26
- [20] = '_', //
27
- [21] = '_', //
28
- [22] = '_', //
29
- [23] = '_', //
30
- [24] = '_', //
31
- [25] = '_', //
32
- [26] = '_', //
33
- [27] = '_', //
34
- [28] = '_', //
35
- [29] = '_', //
36
- [30] = '_', //
37
- [31] = '_', //
38
- [32] = '_', //
39
- [33] = '_', // !
40
- [34] = '_', // "
41
- [35] = '_', // #
42
- [36] = '_', // $
43
- [37] = '_', // %
44
- [38] = '_', // &
45
- [39] = '_', // '
46
- [40] = '_', // (
47
- [41] = '_', // )
48
- [42] = '_', // *
49
- [43] = '_', // +
50
- [44] = '.', // ,
51
- [45] = '-', // -
52
- [46] = '.', // .
53
- [47] = '/', // /
54
- [48] = '0', // 0
55
- [49] = '1', // 1
56
- [50] = '2', // 2
57
- [51] = '3', // 3
58
- [52] = '4', // 4
59
- [53] = '5', // 5
60
- [54] = '6', // 6
61
- [55] = '7', // 7
62
- [56] = '8', // 8
63
- [57] = '9', // 9
64
- [58] = '_', // :
65
- [59] = '_', // ;
66
- [60] = '_', // <
67
- [61] = '_', // =
68
- [62] = '_', // >
69
- [63] = '_', // ?
70
- [64] = '_', // @
71
- [65] = 'a', // A
72
- [66] = 'b', // B
73
- [67] = 'c', // C
74
- [68] = 'd', // D
75
- [69] = 'e', // E
76
- [70] = 'f', // F
77
- [71] = 'g', // G
78
- [72] = 'h', // H
79
- [73] = 'i', // I
80
- [74] = 'j', // J
81
- [75] = 'k', // K
82
- [76] = 'l', // L
83
- [77] = 'm', // M
84
- [78] = 'n', // N
85
- [79] = 'o', // O
86
- [80] = 'p', // P
87
- [81] = 'q', // Q
88
- [82] = 'r', // R
89
- [83] = 's', // S
90
- [84] = 't', // T
91
- [85] = 'u', // U
92
- [86] = 'v', // V
93
- [87] = 'w', // W
94
- [88] = 'x', // X
95
- [89] = 'y', // Y
96
- [90] = 'z', // Z
97
- [91] = '_', // [
98
- [92] = '/', // backslash
99
- [93] = '_', // ]
100
- [94] = '_', // ^
101
- [95] = '_', // _
102
- [96] = '_', // `
103
- [97] = 'a', // a
104
- [98] = 'b', // b
105
- [99] = 'c', // c
106
- [100] = 'd', // d
107
- [101] = 'e', // e
108
- [102] = 'f', // f
109
- [103] = 'g', // g
110
- [104] = 'h', // h
111
- [105] = 'i', // i
112
- [106] = 'j', // j
113
- [107] = 'k', // k
114
- [108] = 'l', // l
115
- [109] = 'm', // m
116
- [110] = 'n', // n
117
- [111] = 'o', // o
118
- [112] = 'p', // p
119
- [113] = 'q', // q
120
- [114] = 'r', // r
121
- [115] = 's', // s
122
- [116] = 't', // t
123
- [117] = 'u', // u
124
- [118] = 'v', // v
125
- [119] = 'w', // w
126
- [120] = 'x', // x
127
- [121] = 'y', // y
128
- [122] = 'z', // z
129
- [123] = '_', // {
130
- [124] = '_', // |
131
- [125] = '_', // }
132
- [126] = '_', // ~
133
- [127] = '_', //
134
- [128] = '_', //
135
- [129] = '_', //
136
- [130] = '_', //
137
- [131] = '_', //
138
- [132] = '_', //
139
- [133] = '_', //
140
- [134] = '_', //
141
- [135] = '_', //
142
- [136] = '_', //
143
- [137] = '_', //
144
- [138] = '_', //
145
- [139] = '_', //
146
- [140] = '_', //
147
- [141] = '_', //
148
- [142] = '_', //
149
- [143] = '_', //
150
- [144] = '_', //
151
- [145] = '_', //
152
- [146] = '_', //
153
- [147] = '_', //
154
- [148] = '_', //
155
- [149] = '_', //
156
- [150] = '_', //
157
- [151] = '_', //
158
- [152] = '_', //
159
- [153] = '_', //
160
- [154] = '_', //
161
- [155] = '_', //
162
- [156] = '_', //
163
- [157] = '_', //
164
- [158] = '_', //
165
- [159] = '_', //
166
- [160] = '_', //
167
- [161] = '_', //
168
- [162] = '_', //
169
- [163] = '_', //
170
- [164] = '_', //
171
- [165] = '_', //
172
- [166] = '_', //
173
- [167] = '_', //
174
- [168] = '_', //
175
- [169] = '_', //
176
- [170] = '_', //
177
- [171] = '_', //
178
- [172] = '_', //
179
- [173] = '_', //
180
- [174] = '_', //
181
- [175] = '_', //
182
- [176] = '_', //
183
- [177] = '_', //
184
- [178] = '_', //
185
- [179] = '_', //
186
- [180] = '_', //
187
- [181] = '_', //
188
- [182] = '_', //
189
- [183] = '_', //
190
- [184] = '_', //
191
- [185] = '_', //
192
- [186] = '_', //
193
- [187] = '_', //
194
- [188] = '_', //
195
- [189] = '_', //
196
- [190] = '_', //
197
- [191] = '_', //
198
- [192] = '_', //
199
- [193] = '_', //
200
- [194] = '_', //
201
- [195] = '_', //
202
- [196] = '_', //
203
- [197] = '_', //
204
- [198] = '_', //
205
- [199] = '_', //
206
- [200] = '_', //
207
- [201] = '_', //
208
- [202] = '_', //
209
- [203] = '_', //
210
- [204] = '_', //
211
- [205] = '_', //
212
- [206] = '_', //
213
- [207] = '_', //
214
- [208] = '_', //
215
- [209] = '_', //
216
- [210] = '_', //
217
- [211] = '_', //
218
- [212] = '_', //
219
- [213] = '_', //
220
- [214] = '_', //
221
- [215] = '_', //
222
- [216] = '_', //
223
- [217] = '_', //
224
- [218] = '_', //
225
- [219] = '_', //
226
- [220] = '_', //
227
- [221] = '_', //
228
- [222] = '_', //
229
- [223] = '_', //
230
- [224] = '_', //
231
- [225] = '_', //
232
- [226] = '_', //
233
- [227] = '_', //
234
- [228] = '_', //
235
- [229] = '_', //
236
- [230] = '_', //
237
- [231] = '_', //
238
- [232] = '_', //
239
- [233] = '_', //
240
- [234] = '_', //
241
- [235] = '_', //
242
- [236] = '_', //
243
- [237] = '_', //
244
- [238] = '_', //
245
- [239] = '_', //
246
- [240] = '_', //
247
- [241] = '_', //
248
- [242] = '_', //
249
- [243] = '_', //
250
- [244] = '_', //
251
- [245] = '_', //
252
- [246] = '_', //
253
- [247] = '_', //
254
- [248] = '_', //
255
- [249] = '_', //
256
- [250] = '_', //
257
- [251] = '_', //
258
- [252] = '_', //
259
- [253] = '_', //
260
- [254] = '_', //
261
- [255] = '_' //
5
+/*
6
+ * ! -> simple patterns negation (only when it is the first character)
7
+ * " -> needs escaping when parsing
8
+ * $ -> can be a shell variable (security in alarm-notify.sh)
9
+ * % -> http GET encoded characters
10
+ * & -> http GET fields separator
11
+ * ' -> needs escaping when parsing
12
+ * * -> simple pattern wildcard
13
+ * + -> http GET space
14
+ * , -> list separator (probably not used today)
15
+ * = -> plugins.d protocol separator
16
+ * ? -> http GET query string separator
17
+ * @ -> hostname separator (on the UI)
18
+ * ` -> bash expansion (security in alarm-notify.sh)
19
+ * | -> list separator (simple patterns and http GET)
20
+ */
21
+
22
+unsigned char chart_names_allowed_chars[256] = {
23
+ [0] = '\0', [1] = ' ', [2] = ' ', [3] = ' ', [4] = ' ', [5] = ' ', [6] = ' ', [7] = ' ', [8] = ' ',
24
+
25
+ // control characters to be treated as spaces
26
+ ['\t'] = ' ', ['\n'] = ' ', ['\v'] = ' ', ['\f'] = ' ', ['\r'] = ' ',
27
+
28
+ [14] = ' ', [15] = ' ', [16] = ' ', [17] = ' ', [18] = ' ', [19] = ' ', [20] = ' ', [21] = ' ',
29
+ [22] = ' ', [23] = ' ', [24] = ' ', [25] = ' ', [26] = ' ', [27] = ' ', [28] = ' ', [29] = ' ',
30
+ [30] = ' ', [31] = ' ',
31
+
32
+ // symbols
33
+ [' '] = ' ', ['!'] = '!', ['"'] = '_', ['#'] = '#', ['$'] = '_', ['%'] = '_', ['&'] = '_', ['\''] = '_',
34
+ ['('] = '(', [')'] = ')', ['*'] = '_', ['+'] = '_', [','] = '.', ['-'] = '-', ['.'] = '.', ['/'] = '/',
35
+
36
+ // numbers
37
+ ['0'] = '0', ['1'] = '1', ['2'] = '2', ['3'] = '3', ['4'] = '4', ['5'] = '5', ['6'] = '6', ['7'] = '7',
38
+ ['8'] = '8', ['9'] = '9',
39
+
40
+ // symbols
41
+ [':'] = ':', [';'] = ';', ['<'] = '<', ['='] = '_', ['>'] = '>', ['?'] = '_', ['@'] = '_',
42
+
43
+ // capitals
44
+ ['A'] = 'A', ['B'] = 'B', ['C'] = 'C', ['D'] = 'D', ['E'] = 'E', ['F'] = 'F', ['G'] = 'G', ['H'] = 'H',
45
+ ['I'] = 'I', ['J'] = 'J', ['K'] = 'K', ['L'] = 'L', ['M'] = 'M', ['N'] = 'N', ['O'] = 'O', ['P'] = 'P',
46
+ ['Q'] = 'Q', ['R'] = 'R', ['S'] = 'S', ['T'] = 'T', ['U'] = 'U', ['V'] = 'V', ['W'] = 'W', ['X'] = 'X',
47
+ ['Y'] = 'Y', ['Z'] = 'Z',
48
+
49
+ // symbols
50
+ ['['] = '[', ['\\'] = '/', [']'] = ']', ['^'] = '_', ['_'] = '_', ['`'] = '_',
51
+
52
+ // lower
53
+ ['a'] = 'a', ['b'] = 'b', ['c'] = 'c', ['d'] = 'd', ['e'] = 'e', ['f'] = 'f', ['g'] = 'g', ['h'] = 'h',
54
+ ['i'] = 'i', ['j'] = 'j', ['k'] = 'k', ['l'] = 'l', ['m'] = 'm', ['n'] = 'n', ['o'] = 'o', ['p'] = 'p',
55
+ ['q'] = 'q', ['r'] = 'r', ['s'] = 's', ['t'] = 't', ['u'] = 'u', ['v'] = 'v', ['w'] = 'w', ['x'] = 'x',
56
+ ['y'] = 'y', ['z'] = 'z',
57
+
58
+ // symbols
59
+ ['{'] = '{', ['|'] = '_', ['}'] = '}', ['~'] = '~',
60
+
61
+ // rest
62
+ [127] = ' ', [128] = ' ', [129] = ' ', [130] = ' ', [131] = ' ', [132] = ' ', [133] = ' ', [134] = ' ',
63
+ [135] = ' ', [136] = ' ', [137] = ' ', [138] = ' ', [139] = ' ', [140] = ' ', [141] = ' ', [142] = ' ',
64
+ [143] = ' ', [144] = ' ', [145] = ' ', [146] = ' ', [147] = ' ', [148] = ' ', [149] = ' ', [150] = ' ',
65
+ [151] = ' ', [152] = ' ', [153] = ' ', [154] = ' ', [155] = ' ', [156] = ' ', [157] = ' ', [158] = ' ',
66
+ [159] = ' ', [160] = ' ', [161] = ' ', [162] = ' ', [163] = ' ', [164] = ' ', [165] = ' ', [166] = ' ',
67
+ [167] = ' ', [168] = ' ', [169] = ' ', [170] = ' ', [171] = ' ', [172] = ' ', [173] = ' ', [174] = ' ',
68
+ [175] = ' ', [176] = ' ', [177] = ' ', [178] = ' ', [179] = ' ', [180] = ' ', [181] = ' ', [182] = ' ',
69
+ [183] = ' ', [184] = ' ', [185] = ' ', [186] = ' ', [187] = ' ', [188] = ' ', [189] = ' ', [190] = ' ',
70
+ [191] = ' ', [192] = ' ', [193] = ' ', [194] = ' ', [195] = ' ', [196] = ' ', [197] = ' ', [198] = ' ',
71
+ [199] = ' ', [200] = ' ', [201] = ' ', [202] = ' ', [203] = ' ', [204] = ' ', [205] = ' ', [206] = ' ',
72
+ [207] = ' ', [208] = ' ', [209] = ' ', [210] = ' ', [211] = ' ', [212] = ' ', [213] = ' ', [214] = ' ',
73
+ [215] = ' ', [216] = ' ', [217] = ' ', [218] = ' ', [219] = ' ', [220] = ' ', [221] = ' ', [222] = ' ',
74
+ [223] = ' ', [224] = ' ', [225] = ' ', [226] = ' ', [227] = ' ', [228] = ' ', [229] = ' ', [230] = ' ',
75
+ [231] = ' ', [232] = ' ', [233] = ' ', [234] = ' ', [235] = ' ', [236] = ' ', [237] = ' ', [238] = ' ',
76
+ [239] = ' ', [240] = ' ', [241] = ' ', [242] = ' ', [243] = ' ', [244] = ' ', [245] = ' ', [246] = ' ',
77
+ [247] = ' ', [248] = ' ', [249] = ' ', [250] = ' ', [251] = ' ', [252] = ' ', [253] = ' ', [254] = ' ',
78
+ [255] = ' '
79
};
80
81
+static inline void sanitize_chart_name(char *dst, const char *src, size_t dst_size) {
82
+ // text_sanitize deduplicates spaces
83
+ text_sanitize((unsigned char *)dst, (const unsigned char *)src, dst_size,
84
+ chart_names_allowed_chars, true, "", NULL);
85
+
86
+ char *d = dst;
87
+
88
+ // do not accept ! as the first character
89
+ if(*d == '!') *d = '_';
90
+
91
+ // convert remaining spaces to underscores
92
+ while(*d) {
93
+ if(*d == ' ') *d = '_';
94
+ d++;
95
+ }
96
+}
97
+
98
// make sure the supplied string
99
// is good for a netdata chart/dimension ID/NAME
100
void netdata_fix_chart_name(char *s) {
267
- while ((*s = netdata_map_chart_names[(uint8_t)*s])) s++;
101
+ sanitize_chart_name(s, s, strlen(s) + 1);
102
}
103
270
-static uint8_t netdata_map_chart_ids[256] = {
271
- [0] = '\0', //
272
- [1] = '_', //
273
- [2] = '_', //
274
- [3] = '_', //
275
- [4] = '_', //
276
- [5] = '_', //
277
- [6] = '_', //
278
- [7] = '_', //
279
- [8] = '_', //
280
- [9] = '_', //
281
- [10] = '_', //
282
- [11] = '_', //
283
- [12] = '_', //
284
- [13] = '_', //
285
- [14] = '_', //
286
- [15] = '_', //
287
- [16] = '_', //
288
- [17] = '_', //
289
- [18] = '_', //
290
- [19] = '_', //
291
- [20] = '_', //
292
- [21] = '_', //
293
- [22] = '_', //
294
- [23] = '_', //
295
- [24] = '_', //
296
- [25] = '_', //
297
- [26] = '_', //
298
- [27] = '_', //
299
- [28] = '_', //
300
- [29] = '_', //
301
- [30] = '_', //
302
- [31] = '_', //
303
- [32] = '_', //
304
- [33] = '_', // !
305
- [34] = '_', // "
306
- [35] = '_', // #
307
- [36] = '_', // $
308
- [37] = '_', // %
309
- [38] = '_', // &
310
- [39] = '_', // '
311
- [40] = '_', // (
312
- [41] = '_', // )
313
- [42] = '_', // *
314
- [43] = '_', // +
315
- [44] = '.', // ,
316
- [45] = '-', // -
317
- [46] = '.', // .
318
- [47] = '_', // /
319
- [48] = '0', // 0
320
- [49] = '1', // 1
321
- [50] = '2', // 2
322
- [51] = '3', // 3
323
- [52] = '4', // 4
324
- [53] = '5', // 5
325
- [54] = '6', // 6
326
- [55] = '7', // 7
327
- [56] = '8', // 8
328
- [57] = '9', // 9
329
- [58] = '_', // :
330
- [59] = '_', // ;
331
- [60] = '_', // <
332
- [61] = '_', // =
333
- [62] = '_', // >
334
- [63] = '_', // ?
335
- [64] = '_', // @
336
- [65] = 'a', // A
337
- [66] = 'b', // B
338
- [67] = 'c', // C
339
- [68] = 'd', // D
340
- [69] = 'e', // E
341
- [70] = 'f', // F
342
- [71] = 'g', // G
343
- [72] = 'h', // H
344
- [73] = 'i', // I
345
- [74] = 'j', // J
346
- [75] = 'k', // K
347
- [76] = 'l', // L
348
- [77] = 'm', // M
349
- [78] = 'n', // N
350
- [79] = 'o', // O
351
- [80] = 'p', // P
352
- [81] = 'q', // Q
353
- [82] = 'r', // R
354
- [83] = 's', // S
355
- [84] = 't', // T
356
- [85] = 'u', // U
357
- [86] = 'v', // V
358
- [87] = 'w', // W
359
- [88] = 'x', // X
360
- [89] = 'y', // Y
361
- [90] = 'z', // Z
362
- [91] = '_', // [
363
- [92] = '_', // backslash
364
- [93] = '_', // ]
365
- [94] = '_', // ^
366
- [95] = '_', // _
367
- [96] = '_', // `
368
- [97] = 'a', // a
369
- [98] = 'b', // b
370
- [99] = 'c', // c
371
- [100] = 'd', // d
372
- [101] = 'e', // e
373
- [102] = 'f', // f
374
- [103] = 'g', // g
375
- [104] = 'h', // h
376
- [105] = 'i', // i
377
- [106] = 'j', // j
378
- [107] = 'k', // k
379
- [108] = 'l', // l
380
- [109] = 'm', // m
381
- [110] = 'n', // n
382
- [111] = 'o', // o
383
- [112] = 'p', // p
384
- [113] = 'q', // q
385
- [114] = 'r', // r
386
- [115] = 's', // s
387
- [116] = 't', // t
388
- [117] = 'u', // u
389
- [118] = 'v', // v
390
- [119] = 'w', // w
391
- [120] = 'x', // x
392
- [121] = 'y', // y
393
- [122] = 'z', // z
394
- [123] = '_', // {
395
- [124] = '_', // |
396
- [125] = '_', // }
397
- [126] = '_', // ~
398
- [127] = '_', //
399
- [128] = '_', //
400
- [129] = '_', //
401
- [130] = '_', //
402
- [131] = '_', //
403
- [132] = '_', //
404
- [133] = '_', //
405
- [134] = '_', //
406
- [135] = '_', //
407
- [136] = '_', //
408
- [137] = '_', //
409
- [138] = '_', //
410
- [139] = '_', //
411
- [140] = '_', //
412
- [141] = '_', //
413
- [142] = '_', //
414
- [143] = '_', //
415
- [144] = '_', //
416
- [145] = '_', //
417
- [146] = '_', //
418
- [147] = '_', //
419
- [148] = '_', //
420
- [149] = '_', //
421
- [150] = '_', //
422
- [151] = '_', //
423
- [152] = '_', //
424
- [153] = '_', //
425
- [154] = '_', //
426
- [155] = '_', //
427
- [156] = '_', //
428
- [157] = '_', //
429
- [158] = '_', //
430
- [159] = '_', //
431
- [160] = '_', //
432
- [161] = '_', //
433
- [162] = '_', //
434
- [163] = '_', //
435
- [164] = '_', //
436
- [165] = '_', //
437
- [166] = '_', //
438
- [167] = '_', //
439
- [168] = '_', //
440
- [169] = '_', //
441
- [170] = '_', //
442
- [171] = '_', //
443
- [172] = '_', //
444
- [173] = '_', //
445
- [174] = '_', //
446
- [175] = '_', //
447
- [176] = '_', //
448
- [177] = '_', //
449
- [178] = '_', //
450
- [179] = '_', //
451
- [180] = '_', //
452
- [181] = '_', //
453
- [182] = '_', //
454
- [183] = '_', //
455
- [184] = '_', //
456
- [185] = '_', //
457
- [186] = '_', //
458
- [187] = '_', //
459
- [188] = '_', //
460
- [189] = '_', //
461
- [190] = '_', //
462
- [191] = '_', //
463
- [192] = '_', //
464
- [193] = '_', //
465
- [194] = '_', //
466
- [195] = '_', //
467
- [196] = '_', //
468
- [197] = '_', //
469
- [198] = '_', //
470
- [199] = '_', //
471
- [200] = '_', //
472
- [201] = '_', //
473
- [202] = '_', //
474
- [203] = '_', //
475
- [204] = '_', //
476
- [205] = '_', //
477
- [206] = '_', //
478
- [207] = '_', //
479
- [208] = '_', //
480
- [209] = '_', //
481
- [210] = '_', //
482
- [211] = '_', //
483
- [212] = '_', //
484
- [213] = '_', //
485
- [214] = '_', //
486
- [215] = '_', //
487
- [216] = '_', //
488
- [217] = '_', //
489
- [218] = '_', //
490
- [219] = '_', //
491
- [220] = '_', //
492
- [221] = '_', //
493
- [222] = '_', //
494
- [223] = '_', //
495
- [224] = '_', //
496
- [225] = '_', //
497
- [226] = '_', //
498
- [227] = '_', //
499
- [228] = '_', //
500
- [229] = '_', //
501
- [230] = '_', //
502
- [231] = '_', //
503
- [232] = '_', //
504
- [233] = '_', //
505
- [234] = '_', //
506
- [235] = '_', //
507
- [236] = '_', //
508
- [237] = '_', //
509
- [238] = '_', //
510
- [239] = '_', //
511
- [240] = '_', //
512
- [241] = '_', //
513
- [242] = '_', //
514
- [243] = '_', //
515
- [244] = '_', //
516
- [245] = '_', //
517
- [246] = '_', //
518
- [247] = '_', //
519
- [248] = '_', //
520
- [249] = '_', //
521
- [250] = '_', //
522
- [251] = '_', //
523
- [252] = '_', //
524
- [253] = '_', //
525
- [254] = '_', //
526
- [255] = '_' //
527
-};
528
-
529
-// make sure the supplied string
530
-// is good for a netdata chart/dimension ID/NAME
104
void netdata_fix_chart_id(char *s) {
532
- while ((*s = netdata_map_chart_ids[(uint8_t) *s])) s++;
105
+ sanitize_chart_name(s, s, strlen(s) + 1);
106
+// size_t len = strlen(s);
107
+// char buf[len + 1];
108
+//
109
+// text_sanitize((unsigned char *)buf, (const unsigned char *)s, sizeof(buf),
110
+// chart_names_allowed_chars, true, "", NULL);
111
+//
112
+// if(memcmp(s, buf, sizeof(buf)) == 0)
113
+// // they are the same
114
+// return;
115
+//
116
+// // they differ
117
+// XXH128_hash_t hash = XXH3_128bits(s, len);
118
+// ND_UUID *uuid = (ND_UUID *)&hash;
119
+// internal_fatal(sizeof(hash) != sizeof(ND_UUID), "XXH128 and ND_UUID do not have the same size");
120
+// buf[0] = 'x';
121
+// buf[1] = 'x';
122
+// buf[2] = 'h';
123
+// buf[3] = '_';
124
+// uuid_unparse_lower_compact(uuid->uuid, &buf[4]);
125
+}
126
+
127
+char *rrdset_strncpyz_name(char *dst, const char *src, size_t dst_size_minus_1) {
128
+ // src starts with "type."
129
+ sanitize_chart_name(dst, src, dst_size_minus_1 + 1);
130
+ return dst;
131
+}
132
+
133
+bool rrdvar_fix_name(char *variable) {
134
+ size_t len = strlen(variable);
135
+ char buf[len + 1];
136
+ memcpy(buf, variable, sizeof(buf));
137
+ sanitize_chart_name(variable, variable, len + 1);
138
+ return memcmp(buf, variable, sizeof(buf)) != 0;
139
}
src/libnetdata/sanitizers/chart_id_and_name.h
+7
@@ -7,5 +7,12 @@
7
8
void netdata_fix_chart_id(char *s);
9
void netdata_fix_chart_name(char *s);
10
+char *rrdset_strncpyz_name(char *dst, const char *src, size_t dst_size_minus_1);
11
+bool rrdvar_fix_name(char *variable);
12
+
13
+extern unsigned char chart_names_allowed_chars[256];
14
+static inline bool is_netdata_api_valid_character(char c) {
15
+ return (IS_UTF8_BYTE(c) || chart_names_allowed_chars[(unsigned char)c] == (unsigned char)c);
16
+}
17
18
#endif //NETDATA_CHART_ID_AND_NAME_H