]> git.ipfire.org Git - telemetry.git/commitdiff
source: Enforce rrdtool's limits on field names
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 28 Nov 2025 16:01:27 +0000 (16:01 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 28 Nov 2025 16:01:27 +0000 (16:01 +0000)
Fields in RRD files can only be up to 19 characters long and may only
contain A-Za-z0-9\-_.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/daemon/source.c

index 74c960983248e7f1a1a814a86e31d9bc9f4644fb..d1f645e7504ba2b4e2d0afb32a96b8fe093bca4a 100644 (file)
@@ -394,6 +394,50 @@ static int td_source_init(td_source* self) {
        return r;
 }
 
+static int td_source_check_data_sources(td_source* self) {
+       for (const td_rrd_ds* ds = self->impl->rrd_dss; ds->field; ds++) {
+               // Check if the field name is empty
+               if (!ds->field || !*ds->field) {
+                       ERROR(self->ctx, "Empty DS field in %s\n", td_source_name(self));
+                       return -EINVAL;
+               }
+
+               // Check field name length
+               size_t length = strlen(ds->field);
+
+               // Fail if it is too long
+               if (length > 19) {
+                       ERROR(self->ctx, "DS field name is too long: %s. "
+                                       "Must be <= 19 characters, but is %ld.\n", ds->field, length);
+                       return -EINVAL;
+               }
+
+               // Check for invalid characters
+               for (const char* p = ds->field; *p; p++) {
+                       // A-Z/a-z are allowed
+                       if (isalpha(*p))
+                               continue;
+
+                       // Digits are allowed
+                       if (isdigit(*p))
+                               continue;
+
+                       // Special characters
+                       switch (*p) {
+                               case '-':
+                               case '_':
+                                       continue;
+
+                               default:
+                                       ERROR(self->ctx, "DS field name contains invalid characters: %s\n", ds->field);
+                                       return -EINVAL;
+                       }
+               }
+       }
+
+       return 0;
+}
+
 static int td_source_check(td_source* self) {
        // Check if name is set
        if (!self->impl->name) {
@@ -408,7 +452,8 @@ static int td_source_check(td_source* self) {
                return -EINVAL;
        }
 
-       return 0;
+       // Check data sources
+       return td_source_check_data_sources(self);
 }
 
 static void td_source_free(td_source* self) {