From 9f22d297f78323cb6ae9e8de66f9390333425df9 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Fri, 2 Jan 2015 15:47:24 +0100 Subject: [PATCH] data: Let sdb_data_parse() accept a const string and copy it if necessary. Given that we need a copy for regex values anyway, this is more consistent. --- src/core/data.c | 17 +++++++++++++---- src/include/core/data.h | 16 ++++------------ src/utils/unixsock.c | 3 +++ t/unit/core/data_test.c | 13 ++++++------- 4 files changed, 26 insertions(+), 23 deletions(-) diff --git a/src/core/data.c b/src/core/data.c index 8c54c93..d34a4dd 100644 --- a/src/core/data.c +++ b/src/core/data.c @@ -1042,12 +1042,17 @@ sdb_data_format(const sdb_data_t *datum, char *buf, size_t buflen, int quoted) } /* sdb_data_format */ int -sdb_data_parse(char *str, int type, sdb_data_t *data) +sdb_data_parse(const char *str, int type, sdb_data_t *data) { sdb_data_t tmp; char *endptr = NULL; + if (! str) { + errno = EINVAL; + return -1; + } + errno = 0; if (type == SDB_TYPE_INTEGER) { tmp.data.integer = strtoll(str, &endptr, 0); @@ -1056,16 +1061,20 @@ sdb_data_parse(char *str, int type, sdb_data_t *data) tmp.data.decimal = strtod(str, &endptr); } else if (type == SDB_TYPE_STRING) { - tmp.data.string = str; + tmp.data.string = strdup(str); + if (! tmp.data.string) + return -1; } else if (type == SDB_TYPE_DATETIME) { double datetime = strtod(str, &endptr); tmp.data.datetime = DOUBLE_TO_SDB_TIME(datetime); } else if (type == SDB_TYPE_BINARY) { - /* we don't support any binary information containing 0-bytes */ + /* we don't support any binary information containing 0-bytes here */ + tmp.data.binary.datum = (unsigned char *)strdup(str); + if (! tmp.data.binary.datum) + return -1; tmp.data.binary.length = strlen(str); - tmp.data.binary.datum = (unsigned char *)str; } else if (type == SDB_TYPE_REGEX) { tmp.data.re.raw = strdup(str); diff --git a/src/include/core/data.h b/src/include/core/data.h index c179fea..c037fb0 100644 --- a/src/include/core/data.h +++ b/src/include/core/data.h @@ -302,24 +302,16 @@ sdb_data_format(const sdb_data_t *datum, char *buf, size_t buflen, int quoted); * character of the string is "0"), sedecimal (base 16, if the string includes * the "0x" prefix), or decimal. Decimal numbers may also be "infinity" or * "NaN" or may use a decimal exponent. Date-time values are expected to be - * specified as (floating point) number of seconds since the epoch. For string - * and binary data, the input string is passed to the datum. The function does - * not allocate new memory for that purpose. Use sdb_data_copy() if you want - * to do that. For regex data, the input string is copied to newly allocated - * memory and also compiled to a regex. Use sdb_data_free_datum() to free the - * dynamically allocated memory. - * - * The input string may be stored in 'data', that is, the function may be used - * to do an inline cast from a string to any other type. It is the callers - * responsibility to free the memory used by the string in case the target - * type does not keep a reference to it. + * specified as (floating point) number of seconds since the epoch. New memory + * will be allocated as necessary and will have to be free'd using + * sdb_data_free_datum(). * * Returns: * - 0 on success * - a negative value else */ int -sdb_data_parse(char *str, int type, sdb_data_t *data); +sdb_data_parse(const char *str, int type, sdb_data_t *data); /* * sdb_data_sizeof: diff --git a/src/utils/unixsock.c b/src/utils/unixsock.c index 6f4d5cc..6536641 100644 --- a/src/utils/unixsock.c +++ b/src/utils/unixsock.c @@ -134,6 +134,9 @@ sdb_unixsock_client_process_one_line(sdb_unixsock_client_t *client, if (callback(client, (size_t)column_count, data, user_data)) return -1; + + for (i = 0; i < column_count; ++i) + sdb_data_free_datum(&data[i]); return 0; } /* sdb_unixsock_client_process_one_line */ diff --git a/t/unit/core/data_test.c b/t/unit/core/data_test.c index 2b32d8b..cf26035 100644 --- a/t/unit/core/data_test.c +++ b/t/unit/core/data_test.c @@ -2168,19 +2168,18 @@ START_TEST(test_parse) golden_data[i].input, type); if (type == SDB_TYPE_STRING) - fail_unless(golden_data[i].input == result.data.string, - "sdb_data_parse(%s, %d, ) modified input string", + fail_unless(golden_data[i].input != result.data.string, + "sdb_data_parse(%s, %d, ) copied input string", golden_data[i].input, type); if (type == SDB_TYPE_BINARY) - fail_unless(golden_data[i].input == (char *)result.data.binary.datum, - "sdb_data_parse(%s, %d, ) modified input string", + fail_unless(golden_data[i].input != (char *)result.data.binary.datum, + "sdb_data_parse(%s, %d, ) copied input string", golden_data[i].input, type); - if (type == SDB_TYPE_REGEX) { + if (type == SDB_TYPE_REGEX) fail_unless(golden_data[i].input != result.data.re.raw, "sdb_data_parse(%s, %d, ) copied input string", golden_data[i].input, type); - sdb_data_free_datum(&result); - } + sdb_data_free_datum(&result); } } END_TEST -- 2.30.2