]> git.ipfire.org Git - thirdparty/collectd.git/commitdiff
common: Change `parse_values` so it doesn't modify the parsed string.
authorFlorian Forster <octo@collectd.org>
Wed, 20 Dec 2023 19:45:49 +0000 (20:45 +0100)
committerFlorian Forster <octo@collectd.org>
Wed, 20 Dec 2023 19:45:49 +0000 (20:45 +0100)
src/utils/common/common.c
src/utils/common/common.h
src/utils/common/common_test.c

index d154446141422621dd6ee65bfa31a9780a41db00..1dd383995d45d8fc86aa3b17fead87cf199704a5 100644 (file)
@@ -1109,19 +1109,18 @@ int parse_value(const char *value_orig, value_t *ret_value, int ds_type) {
   return 0;
 } /* int parse_value */
 
-int parse_values(char *buffer, value_list_t *vl, const data_set_t *ds) {
-  size_t i;
-  char *dummy;
-  char *ptr;
-  char *saveptr;
-
-  if ((buffer == NULL) || (vl == NULL) || (ds == NULL))
+int parse_values(char const *s, value_list_t *vl, const data_set_t *ds) {
+  if ((s == NULL) || (vl == NULL) || (ds == NULL))
     return EINVAL;
 
-  i = 0;
-  dummy = buffer;
-  saveptr = NULL;
+  char *buffer = sstrdup(s);
+
+  size_t i = 0;
+  char *dummy = buffer;
+  char *saveptr = NULL;
   vl->time = 0;
+
+  char *ptr;
   while ((ptr = strtok_r(dummy, ":", &saveptr)) != NULL) {
     dummy = NULL;
 
@@ -1140,11 +1139,13 @@ int parse_values(char *buffer, value_list_t *vl, const data_set_t *ds) {
 
         errno = 0;
         tmp = strtod(ptr, &endptr);
-        if ((errno != 0)        /* Overflow */
-            || (endptr == ptr)  /* Invalid string */
-            || (endptr == NULL) /* This should not happen */
-            || (*endptr != 0))  /* Trailing chars */
+        if ((errno != 0)         /* Overflow */
+            || (endptr == ptr)   /* Invalid string */
+            || (endptr == NULL)  /* This should not happen */
+            || (*endptr != 0)) { /* Trailing chars */
+          sfree(buffer);
           return -1;
+        }
 
         vl->time = DOUBLE_TO_CDTIME_T(tmp);
       }
@@ -1152,16 +1153,20 @@ int parse_values(char *buffer, value_list_t *vl, const data_set_t *ds) {
       continue;
     }
 
-    if ((strcmp("U", ptr) == 0) && (ds->ds[i].type == DS_TYPE_GAUGE))
+    if ((strcmp("U", ptr) == 0) && (ds->ds[i].type == DS_TYPE_GAUGE)) {
       vl->values[i].gauge = NAN;
-    else if (0 != parse_value(ptr, &vl->values[i], ds->ds[i].type))
+    } else if (0 != parse_value(ptr, &vl->values[i], ds->ds[i].type)) {
+      sfree(buffer);
       return -1;
+    }
 
     i++;
   } /* while (strtok_r) */
 
-  if ((ptr != NULL) || (i == 0))
+  sfree(buffer);
+  if ((ptr != NULL) || (i == 0)) {
     return -1;
+  }
   return 0;
 } /* int parse_values */
 
index feae1aba86da3e84d63c3eaeeed2f962b097125a..19929434cf7ae757cabf5b447682bebe03624b81 100644 (file)
@@ -332,7 +332,7 @@ int parse_identifier(char *str, char **ret_host, char **ret_plugin,
                      char **ret_type_instance, char *default_host);
 int parse_identifier_vl(const char *str, value_list_t *vl);
 int parse_value(const char *value, value_t *ret_value, int ds_type);
-int parse_values(char *buffer, value_list_t *vl, const data_set_t *ds);
+int parse_values(char const *s, value_list_t *vl, const data_set_t *ds);
 
 /* parse_value_file reads "path" and parses its content as an integer or
  * floating point, depending on "ds_type". On success, the value is stored in
index b8b3b4f7a2bcb15932ed9b014e9a8d66c61ace24..c044336a2b7ecb804cf595d8bdee55ddda82c9e6 100644 (file)
@@ -311,8 +311,16 @@ DEF_TEST(parse_values) {
         .meta = NULL,
     };
 
+    size_t buf_sz = strlen(cases[i].buffer)+1;
+    char buf[buf_sz];
+    strncpy(buf, cases[i].buffer, buf_sz);
+
     int status = parse_values(cases[i].buffer, &vl, &ds);
     EXPECT_EQ_INT(cases[i].status, status);
+
+    /* Ensure cases[i].buffer remains unmodified. */
+    EXPECT_EQ_STR(buf, cases[i].buffer);
+
     if (status != 0)
       continue;