From: Florian Forster Date: Wed, 20 Dec 2023 19:45:49 +0000 (+0100) Subject: common: Change `parse_values` so it doesn't modify the parsed string. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5278b8b73a65e326ea2ea4332d19becad28dcc16;p=thirdparty%2Fcollectd.git common: Change `parse_values` so it doesn't modify the parsed string. --- diff --git a/src/utils/common/common.c b/src/utils/common/common.c index d15444614..1dd383995 100644 --- a/src/utils/common/common.c +++ b/src/utils/common/common.c @@ -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 */ diff --git a/src/utils/common/common.h b/src/utils/common/common.h index feae1aba8..19929434c 100644 --- a/src/utils/common/common.h +++ b/src/utils/common/common.h @@ -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 diff --git a/src/utils/common/common_test.c b/src/utils/common/common_test.c index b8b3b4f7a..c044336a2 100644 --- a/src/utils/common/common_test.c +++ b/src/utils/common/common_test.c @@ -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;