* Re: [PATCH lttng-tools] utils: Rework utils_parse_size_suffix
@ 2014-04-10 20:22 Thibault, Daniel
0 siblings, 0 replies; 7+ messages in thread
From: Thibault, Daniel @ 2014-04-10 20:22 UTC (permalink / raw)
To: lttng-dev
----------------------------------------------------------------------
Date: Thu, 10 Apr 2014 14:43:38 -0400
From: Simon Marchi <simon.marchi@polymtl.ca>
>>>> Should be "[...] should not begin with '-' [...]" (although it is
>>>> true the size string should not *contain*, the test is only for
>>>> *begins with*)
> I meant for it to search in the whole string, and that is what I think strchr does.
Oops, my bad.
> [...]
> + if (num_end == str) {
> + /* strtoull parsed nothing, not good. */
> + DBG("utils_parse_size_suffix: strtoull had nothing good to parse.\n");
> + ret = -1;
> + goto end;
> + }
>
>>>> "utils_parse_size_suffix: zero-length size string." would be clearer. Also note that the preceding DBG strings did not end with '\n'.
> This test indeed will catch zero-length strings. However, if you pass "hello", or "k", strtoull will just parse 0 characters and return the value 0. This test is for these cases as well, which are not zero-length strings. I agree that it's not very clear, but I have nothing better...
How about " utils_parse_size_suffix: size string does not begin with a number."?
Daniel U. Thibault
Protection des systèmes et contremesures (PSC) | Systems Protection & Countermeasures (SPC)
Cyber sécurité pour les missions essentielles (CME) | Mission Critical Cyber Security (MCCS)
R & D pour la défense Canada - Valcartier (RDDC Valcartier) | Defence R&D Canada - Valcartier (DRDC Valcartier)
2459 route de la Bravoure
Québec QC G3J 1X5
CANADA
Vox : (418) 844-4000 x4245
Fax : (418) 844-4538
NAC : 918V QSDJ <http://www.travelgis.com/map.asp?addr=918V%20QSDJ>
Gouvernement du Canada | Government of Canada
<http://www.valcartier.drdc-rddc.gc.ca/>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH lttng-tools] utils: Rework utils_parse_size_suffix
[not found] <1397143819-4563-1-git-send-email-simon.marchi@polymtl.ca>
2014-04-10 19:57 ` David Goulet
[not found] ` <20140410195751.GE28773@dalia>
@ 2014-04-14 14:44 ` David Goulet
2 siblings, 0 replies; 7+ messages in thread
From: David Goulet @ 2014-04-14 14:44 UTC (permalink / raw)
To: Simon Marchi; +Cc: lttng-dev
[-- Attachment #1.1: Type: text/plain, Size: 8442 bytes --]
Merged Thanks.
David
On 10 Apr (11:30:19), Simon Marchi wrote:
> Ok, so there are a lot of problems with this function (sorry :|). Taking
> the regex road is probably to complicated for nothing, so here is a
> version without regexes.
>
> I added many test cases as suggested by Sandeep Chaudhary and Daniel
> Thibault. I tested on both Intel 32 and 64 bits.
>
> Would fix #633
>
> Signed-off-by: Simon Marchi <simon.marchi@polymtl.ca>
> ---
> src/common/utils.c | 136 +++++++++++++-----------------
> src/common/utils.h | 2 +-
> tests/unit/test_utils_parse_size_suffix.c | 54 +++++++++++-
> 3 files changed, 111 insertions(+), 81 deletions(-)
>
> diff --git a/src/common/utils.c b/src/common/utils.c
> index 31596dd..9326080 100644
> --- a/src/common/utils.c
> +++ b/src/common/utils.c
> @@ -28,7 +28,6 @@
> #include <sys/types.h>
> #include <unistd.h>
> #include <inttypes.h>
> -#include <regex.h>
> #include <grp.h>
> #include <pwd.h>
>
> @@ -650,42 +649,10 @@ error:
> return ret;
> }
>
> -/**
> - * Prints the error message corresponding to a regex error code.
> - *
> - * @param errcode The error code.
> - * @param regex The regex object that produced the error code.
> - */
> -static void regex_print_error(int errcode, regex_t *regex)
> -{
> - /* Get length of error message and allocate accordingly */
> - size_t length;
> - char *buffer;
> -
> - assert(regex != NULL);
> -
> - length = regerror(errcode, regex, NULL, 0);
> - if (length == 0) {
> - ERR("regerror returned a length of 0");
> - return;
> - }
> -
> - buffer = zmalloc(length);
> - if (!buffer) {
> - ERR("regex_print_error: zmalloc failed");
> - return;
> - }
> -
> - /* Get and print error message */
> - regerror(errcode, regex, buffer, length);
> - ERR("regex error: %s\n", buffer);
> - free(buffer);
> -
> -}
>
> /**
> * Parse a string that represents a size in human readable format. It
> - * supports decimal integers suffixed by 'k', 'M' or 'G'.
> + * supports decimal integers suffixed by 'k', 'K', 'M' or 'G'.
> *
> * The suffix multiply the integer by:
> * 'k': 1024
> @@ -693,83 +660,94 @@ static void regex_print_error(int errcode, regex_t *regex)
> * 'G': 1024^3
> *
> * @param str The string to parse.
> - * @param size Pointer to a size_t that will be filled with the
> + * @param size Pointer to a uint64_t that will be filled with the
> * resulting size.
> *
> * @return 0 on success, -1 on failure.
> */
> LTTNG_HIDDEN
> -int utils_parse_size_suffix(char *str, uint64_t *size)
> +int utils_parse_size_suffix(const char * const str, uint64_t * const size)
> {
> - regex_t regex;
> int ret;
> - const int nmatch = 3;
> - regmatch_t suffix_match, matches[nmatch];
> - unsigned long long base_size;
> + uint64_t base_size;
> long shift = 0;
> + const char *str_end;
> + char *num_end;
>
> if (!str) {
> - return 0;
> - }
> -
> - /* Compile regex */
> - ret = regcomp(®ex, "^\\(0x\\)\\{0,1\\}[0-9][0-9]*\\([kKMG]\\{0,1\\}\\)$", 0);
> - if (ret != 0) {
> - regex_print_error(ret, ®ex);
> + DBG("utils_parse_size_suffix: received a NULL string.");
> ret = -1;
> goto end;
> }
>
> - /* Match regex */
> - ret = regexec(®ex, str, nmatch, matches, 0);
> - if (ret != 0) {
> + /* strtoull will accept a negative number, but we don't want to. */
> + if (strchr(str, '-') != NULL) {
> + DBG("utils_parse_size_suffix: invalid size string, should not contain '-'.");
> ret = -1;
> - goto free;
> + goto end;
> }
>
> - /* There is a match ! */
> + /* str_end will point to the \0 */
> + str_end = str + strlen(str);
> errno = 0;
> - base_size = strtoull(str, NULL, 0);
> + base_size = strtoull(str, &num_end, 0);
> if (errno != 0) {
> - PERROR("strtoull");
> + PERROR("utils_parse_size_suffix strtoull");
> ret = -1;
> - goto free;
> + goto end;
> }
>
> - /* Check if there is a suffix */
> - suffix_match = matches[2];
> - if (suffix_match.rm_eo - suffix_match.rm_so == 1) {
> - switch (*(str + suffix_match.rm_so)) {
> - case 'K':
> - case 'k':
> - shift = KIBI_LOG2;
> - break;
> - case 'M':
> - shift = MEBI_LOG2;
> - break;
> - case 'G':
> - shift = GIBI_LOG2;
> - break;
> - default:
> - ERR("parse_human_size: invalid suffix");
> - ret = -1;
> - goto free;
> - }
> + if (num_end == str) {
> + /* strtoull parsed nothing, not good. */
> + DBG("utils_parse_size_suffix: strtoull had nothing good to parse.\n");
> + ret = -1;
> + goto end;
> + }
> +
> + /* Check if a prefix is present. */
> + switch (*num_end) {
> + case 'G':
> + shift = GIBI_LOG2;
> + num_end++;
> + break;
> +
> + case 'M': /* */
> + shift = MEBI_LOG2;
> + num_end++;
> + break;
> +
> + case 'K':
> + case 'k':
> + shift = KIBI_LOG2;
> + num_end++;
> + break;
> +
> + case '\0':
> + break;
> +
> + default:
> + DBG("utils_parse_size_suffix: invalid suffix.\n");
> + ret = -1;
> + goto end;
> + }
> +
> + /* Check for garbage after the valid input. */
> + if (num_end != str_end) {
> + DBG("utils_parse_size_suffix: Garbage after size string.");
> + ret = -1;
> + goto end;
> }
>
> *size = base_size << shift;
>
> /* Check for overflow */
> if ((*size >> shift) != base_size) {
> - ERR("parse_size_suffix: oops, overflow detected.");
> + DBG("utils_parse_size_suffix: oops, overflow detected.");
> ret = -1;
> - goto free;
> + goto end;
> }
>
> ret = 0;
> -
> -free:
> - regfree(®ex);
> end:
> return ret;
> }
> diff --git a/src/common/utils.h b/src/common/utils.h
> index 63290a7..b872b53 100644
> --- a/src/common/utils.h
> +++ b/src/common/utils.h
> @@ -43,7 +43,7 @@ int utils_create_stream_file(const char *path_name, char *file_name, uint64_t si
> int utils_rotate_stream_file(char *path_name, char *file_name, uint64_t size,
> uint64_t count, int uid, int gid, int out_fd, uint64_t *new_count,
> int *stream_fd);
> -int utils_parse_size_suffix(char *str, uint64_t *size);
> +int utils_parse_size_suffix(char const * const str, uint64_t * const size);
> int utils_get_count_order_u32(uint32_t x);
> char *utils_get_home_dir(void);
> char *utils_get_user_home_dir(uid_t uid);
> diff --git a/tests/unit/test_utils_parse_size_suffix.c b/tests/unit/test_utils_parse_size_suffix.c
> index 990aa1b..45a87b0 100644
> --- a/tests/unit/test_utils_parse_size_suffix.c
> +++ b/tests/unit/test_utils_parse_size_suffix.c
> @@ -43,11 +43,63 @@ static struct valid_test_input valid_tests_inputs[] = {
> { "0x1234k", 4771840 },
> { "32M", 33554432 },
> { "1024G", 1099511627776 },
> + { "0X400", 1024 },
> + { "0x40a", 1034 },
> + { "0X40b", 1035 },
> + { "0x40C", 1036 },
> + { "0X40D", 1037 },
> + { "0x40e", 1038 },
> + { "0X40f", 1039 },
> + { "00", 0 },
> + { "0k", 0 },
> + { "0K", 0 },
> + { "0M", 0 },
> + { "0G", 0 },
> + { "00k", 0 },
> + { "00K", 0 },
> + { "00M", 0 },
> + { "00G", 0 },
> + { "0x0", 0 },
> + { "0X0", 0 },
> + { "0x0k", 0 },
> + { "0X0K", 0 },
> + { "0x0M", 0 },
> + { "0X0G", 0 },
> + { "0X40G", 68719476736 },
> + { "0300k", 196608 },
> + { "0300K", 196608 },
> + { "030M", 25165824 },
> + { "020G", 17179869184 },
> + { "0xa0k", 163840 },
> + { "0xa0K", 163840 },
> + { "0XA0M", 167772160 },
> + { "0xA0G", 171798691840 },
> };
> static const int num_valid_tests = sizeof(valid_tests_inputs) / sizeof(valid_tests_inputs[0]);
>
> /* Invalid test cases */
> -static char *invalid_tests_inputs[] = { "", "-1", "k", "4611686018427387904G" };
> +static char *invalid_tests_inputs[] = {
> + "",
> + " ",
> + "-1",
> + "k",
> + "4611686018427387904G",
> + "0x40g",
> + "08",
> + "09",
> + "0x",
> + "x0",
> + "0xx0",
> + "07kK",
> + "0xk",
> + "0XM",
> + "0xG",
> + "0x0MM",
> + "0X0GG",
> + "0a",
> + "0B",
> +};
> +
> static const int num_invalid_tests = sizeof(invalid_tests_inputs) / sizeof(invalid_tests_inputs[0]);
>
> static void test_utils_parse_size_suffix(void)
> --
> 1.9.1
>
>
> _______________________________________________
> lttng-dev mailing list
> lttng-dev@lists.lttng.org
> http://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev
[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 603 bytes --]
[-- Attachment #2: Type: text/plain, Size: 155 bytes --]
_______________________________________________
lttng-dev mailing list
lttng-dev@lists.lttng.org
http://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH lttng-tools] utils: Rework utils_parse_size_suffix
[not found] ` <20140410195751.GE28773@dalia>
@ 2014-04-10 20:14 ` Simon Marchi
0 siblings, 0 replies; 7+ messages in thread
From: Simon Marchi @ 2014-04-10 20:14 UTC (permalink / raw)
To: David Goulet; +Cc: lttng-dev
On 10 April 2014 15:57, David Goulet <dgoulet@efficios.com> wrote:
> On 10 Apr (11:30:19), Simon Marchi wrote:
>> Ok, so there are a lot of problems with this function (sorry :|). Taking
>> the regex road is probably to complicated for nothing, so here is a
>> version without regexes.
>>
>> I added many test cases as suggested by Sandeep Chaudhary and Daniel
>> Thibault. I tested on both Intel 32 and 64 bits.
>>
>> Would fix #633
>
> Why are you not sure of that? :P
Would fix if merged :P
> Can you explain *why* regex was a bad choice here (if the 633 ticket
> does not already explain it).
I did not say it was a *bad* choice, but when I look at the old and
new function, the new one seems less cryptic (without the matches and
all). This is debatable.
> Thanks!
> David
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH lttng-tools] utils: Rework utils_parse_size_suffix
[not found] <1397143819-4563-1-git-send-email-simon.marchi@polymtl.ca>
@ 2014-04-10 19:57 ` David Goulet
[not found] ` <20140410195751.GE28773@dalia>
2014-04-14 14:44 ` David Goulet
2 siblings, 0 replies; 7+ messages in thread
From: David Goulet @ 2014-04-10 19:57 UTC (permalink / raw)
To: Simon Marchi; +Cc: lttng-dev
[-- Attachment #1.1: Type: text/plain, Size: 8574 bytes --]
On 10 Apr (11:30:19), Simon Marchi wrote:
> Ok, so there are a lot of problems with this function (sorry :|). Taking
> the regex road is probably to complicated for nothing, so here is a
> version without regexes.
>
> I added many test cases as suggested by Sandeep Chaudhary and Daniel
> Thibault. I tested on both Intel 32 and 64 bits.
>
> Would fix #633
Why are you not sure of that? :P
Can you explain *why* regex was a bad choice here (if the 633 ticket
does not already explain it).
Thanks!
David
>
> Signed-off-by: Simon Marchi <simon.marchi@polymtl.ca>
> ---
> src/common/utils.c | 136 +++++++++++++-----------------
> src/common/utils.h | 2 +-
> tests/unit/test_utils_parse_size_suffix.c | 54 +++++++++++-
> 3 files changed, 111 insertions(+), 81 deletions(-)
>
> diff --git a/src/common/utils.c b/src/common/utils.c
> index 31596dd..9326080 100644
> --- a/src/common/utils.c
> +++ b/src/common/utils.c
> @@ -28,7 +28,6 @@
> #include <sys/types.h>
> #include <unistd.h>
> #include <inttypes.h>
> -#include <regex.h>
> #include <grp.h>
> #include <pwd.h>
>
> @@ -650,42 +649,10 @@ error:
> return ret;
> }
>
> -/**
> - * Prints the error message corresponding to a regex error code.
> - *
> - * @param errcode The error code.
> - * @param regex The regex object that produced the error code.
> - */
> -static void regex_print_error(int errcode, regex_t *regex)
> -{
> - /* Get length of error message and allocate accordingly */
> - size_t length;
> - char *buffer;
> -
> - assert(regex != NULL);
> -
> - length = regerror(errcode, regex, NULL, 0);
> - if (length == 0) {
> - ERR("regerror returned a length of 0");
> - return;
> - }
> -
> - buffer = zmalloc(length);
> - if (!buffer) {
> - ERR("regex_print_error: zmalloc failed");
> - return;
> - }
> -
> - /* Get and print error message */
> - regerror(errcode, regex, buffer, length);
> - ERR("regex error: %s\n", buffer);
> - free(buffer);
> -
> -}
>
> /**
> * Parse a string that represents a size in human readable format. It
> - * supports decimal integers suffixed by 'k', 'M' or 'G'.
> + * supports decimal integers suffixed by 'k', 'K', 'M' or 'G'.
> *
> * The suffix multiply the integer by:
> * 'k': 1024
> @@ -693,83 +660,94 @@ static void regex_print_error(int errcode, regex_t *regex)
> * 'G': 1024^3
> *
> * @param str The string to parse.
> - * @param size Pointer to a size_t that will be filled with the
> + * @param size Pointer to a uint64_t that will be filled with the
> * resulting size.
> *
> * @return 0 on success, -1 on failure.
> */
> LTTNG_HIDDEN
> -int utils_parse_size_suffix(char *str, uint64_t *size)
> +int utils_parse_size_suffix(const char * const str, uint64_t * const size)
> {
> - regex_t regex;
> int ret;
> - const int nmatch = 3;
> - regmatch_t suffix_match, matches[nmatch];
> - unsigned long long base_size;
> + uint64_t base_size;
> long shift = 0;
> + const char *str_end;
> + char *num_end;
>
> if (!str) {
> - return 0;
> - }
> -
> - /* Compile regex */
> - ret = regcomp(®ex, "^\\(0x\\)\\{0,1\\}[0-9][0-9]*\\([kKMG]\\{0,1\\}\\)$", 0);
> - if (ret != 0) {
> - regex_print_error(ret, ®ex);
> + DBG("utils_parse_size_suffix: received a NULL string.");
> ret = -1;
> goto end;
> }
>
> - /* Match regex */
> - ret = regexec(®ex, str, nmatch, matches, 0);
> - if (ret != 0) {
> + /* strtoull will accept a negative number, but we don't want to. */
> + if (strchr(str, '-') != NULL) {
> + DBG("utils_parse_size_suffix: invalid size string, should not contain '-'.");
> ret = -1;
> - goto free;
> + goto end;
> }
>
> - /* There is a match ! */
> + /* str_end will point to the \0 */
> + str_end = str + strlen(str);
> errno = 0;
> - base_size = strtoull(str, NULL, 0);
> + base_size = strtoull(str, &num_end, 0);
> if (errno != 0) {
> - PERROR("strtoull");
> + PERROR("utils_parse_size_suffix strtoull");
> ret = -1;
> - goto free;
> + goto end;
> }
>
> - /* Check if there is a suffix */
> - suffix_match = matches[2];
> - if (suffix_match.rm_eo - suffix_match.rm_so == 1) {
> - switch (*(str + suffix_match.rm_so)) {
> - case 'K':
> - case 'k':
> - shift = KIBI_LOG2;
> - break;
> - case 'M':
> - shift = MEBI_LOG2;
> - break;
> - case 'G':
> - shift = GIBI_LOG2;
> - break;
> - default:
> - ERR("parse_human_size: invalid suffix");
> - ret = -1;
> - goto free;
> - }
> + if (num_end == str) {
> + /* strtoull parsed nothing, not good. */
> + DBG("utils_parse_size_suffix: strtoull had nothing good to parse.\n");
> + ret = -1;
> + goto end;
> + }
> +
> + /* Check if a prefix is present. */
> + switch (*num_end) {
> + case 'G':
> + shift = GIBI_LOG2;
> + num_end++;
> + break;
> +
> + case 'M': /* */
> + shift = MEBI_LOG2;
> + num_end++;
> + break;
> +
> + case 'K':
> + case 'k':
> + shift = KIBI_LOG2;
> + num_end++;
> + break;
> +
> + case '\0':
> + break;
> +
> + default:
> + DBG("utils_parse_size_suffix: invalid suffix.\n");
> + ret = -1;
> + goto end;
> + }
> +
> + /* Check for garbage after the valid input. */
> + if (num_end != str_end) {
> + DBG("utils_parse_size_suffix: Garbage after size string.");
> + ret = -1;
> + goto end;
> }
>
> *size = base_size << shift;
>
> /* Check for overflow */
> if ((*size >> shift) != base_size) {
> - ERR("parse_size_suffix: oops, overflow detected.");
> + DBG("utils_parse_size_suffix: oops, overflow detected.");
> ret = -1;
> - goto free;
> + goto end;
> }
>
> ret = 0;
> -
> -free:
> - regfree(®ex);
> end:
> return ret;
> }
> diff --git a/src/common/utils.h b/src/common/utils.h
> index 63290a7..b872b53 100644
> --- a/src/common/utils.h
> +++ b/src/common/utils.h
> @@ -43,7 +43,7 @@ int utils_create_stream_file(const char *path_name, char *file_name, uint64_t si
> int utils_rotate_stream_file(char *path_name, char *file_name, uint64_t size,
> uint64_t count, int uid, int gid, int out_fd, uint64_t *new_count,
> int *stream_fd);
> -int utils_parse_size_suffix(char *str, uint64_t *size);
> +int utils_parse_size_suffix(char const * const str, uint64_t * const size);
> int utils_get_count_order_u32(uint32_t x);
> char *utils_get_home_dir(void);
> char *utils_get_user_home_dir(uid_t uid);
> diff --git a/tests/unit/test_utils_parse_size_suffix.c b/tests/unit/test_utils_parse_size_suffix.c
> index 990aa1b..45a87b0 100644
> --- a/tests/unit/test_utils_parse_size_suffix.c
> +++ b/tests/unit/test_utils_parse_size_suffix.c
> @@ -43,11 +43,63 @@ static struct valid_test_input valid_tests_inputs[] = {
> { "0x1234k", 4771840 },
> { "32M", 33554432 },
> { "1024G", 1099511627776 },
> + { "0X400", 1024 },
> + { "0x40a", 1034 },
> + { "0X40b", 1035 },
> + { "0x40C", 1036 },
> + { "0X40D", 1037 },
> + { "0x40e", 1038 },
> + { "0X40f", 1039 },
> + { "00", 0 },
> + { "0k", 0 },
> + { "0K", 0 },
> + { "0M", 0 },
> + { "0G", 0 },
> + { "00k", 0 },
> + { "00K", 0 },
> + { "00M", 0 },
> + { "00G", 0 },
> + { "0x0", 0 },
> + { "0X0", 0 },
> + { "0x0k", 0 },
> + { "0X0K", 0 },
> + { "0x0M", 0 },
> + { "0X0G", 0 },
> + { "0X40G", 68719476736 },
> + { "0300k", 196608 },
> + { "0300K", 196608 },
> + { "030M", 25165824 },
> + { "020G", 17179869184 },
> + { "0xa0k", 163840 },
> + { "0xa0K", 163840 },
> + { "0XA0M", 167772160 },
> + { "0xA0G", 171798691840 },
> };
> static const int num_valid_tests = sizeof(valid_tests_inputs) / sizeof(valid_tests_inputs[0]);
>
> /* Invalid test cases */
> -static char *invalid_tests_inputs[] = { "", "-1", "k", "4611686018427387904G" };
> +static char *invalid_tests_inputs[] = {
> + "",
> + " ",
> + "-1",
> + "k",
> + "4611686018427387904G",
> + "0x40g",
> + "08",
> + "09",
> + "0x",
> + "x0",
> + "0xx0",
> + "07kK",
> + "0xk",
> + "0XM",
> + "0xG",
> + "0x0MM",
> + "0X0GG",
> + "0a",
> + "0B",
> +};
> +
> static const int num_invalid_tests = sizeof(invalid_tests_inputs) / sizeof(invalid_tests_inputs[0]);
>
> static void test_utils_parse_size_suffix(void)
> --
> 1.9.1
>
>
> _______________________________________________
> lttng-dev mailing list
> lttng-dev@lists.lttng.org
> http://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev
[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 603 bytes --]
[-- Attachment #2: Type: text/plain, Size: 155 bytes --]
_______________________________________________
lttng-dev mailing list
lttng-dev@lists.lttng.org
http://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH lttng-tools] utils: Rework utils_parse_size_suffix
[not found] <48CF5AC71E61DB46B70D0F388054EFFD3599C114@VAL-E-01.valcartier.drdc-rddc.gc.ca>
@ 2014-04-10 18:43 ` Simon Marchi
0 siblings, 0 replies; 7+ messages in thread
From: Simon Marchi @ 2014-04-10 18:43 UTC (permalink / raw)
To: Thibault, Daniel; +Cc: lttng-dev
Thanks for the comments.
> @@ -693,83 +660,94 @@ static void regex_print_error(int errcode, regex_t *regex)
> [...]
> + /* strtoull will accept a negative number, but we don't want to. */
> + if (strchr(str, '-') != NULL) {
> + DBG("utils_parse_size_suffix: invalid size string, should not contain '-'.");
> ret = -1;
> + goto end;
> }
>
>>>> Should be "[...] should not begin with '-' [...]" (although it is true the size string should not *contain*, the test is only for *begins with*)
I meant for it to search in the whole string, and that is what I think
strchr does.
> [...]
> + if (num_end == str) {
> + /* strtoull parsed nothing, not good. */
> + DBG("utils_parse_size_suffix: strtoull had nothing good to parse.\n");
> + ret = -1;
> + goto end;
> + }
>
>>>> "utils_parse_size_suffix: zero-length size string." would be clearer. Also note that the preceding DBG strings did not end with '\n'.
This test indeed will catch zero-length strings. However, iif you pass
"hello", or "k", strtoull will just parse 0 characters and return the
value 0. This test is for these cases as well, which are not
zero-length strings. I agree that it's not very clear, but I have
nothing better...
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH lttng-tools] utils: Rework utils_parse_size_suffix
@ 2014-04-10 18:31 Thibault, Daniel
0 siblings, 0 replies; 7+ messages in thread
From: Thibault, Daniel @ 2014-04-10 18:31 UTC (permalink / raw)
To: lttng-dev
----------------------------------------------------------------------
Date: Thu, 10 Apr 2014 11:30:19 -0400
From: Simon Marchi <simon.marchi@polymtl.ca>
+++ b/src/common/utils.c
@@ -650,42 +649,10 @@ error:
[...]
* The suffix multiply the integer by:
>>> Should be "The suffixes multiply the integer by:"
@@ -693,83 +660,94 @@ static void regex_print_error(int errcode, regex_t *regex)
[...]
+ /* strtoull will accept a negative number, but we don't want to. */
+ if (strchr(str, '-') != NULL) {
+ DBG("utils_parse_size_suffix: invalid size string, should not contain '-'.");
ret = -1;
+ goto end;
}
>>> Should be "[...] should not begin with '-' [...]" (although it is true the size string should not *contain*, the test is only for *begins with*)
[...]
+ if (num_end == str) {
+ /* strtoull parsed nothing, not good. */
+ DBG("utils_parse_size_suffix: strtoull had nothing good to parse.\n");
+ ret = -1;
+ goto end;
+ }
>>> "utils_parse_size_suffix: zero-length size string." would be clearer. Also note that the preceding DBG strings did not end with '\n'.
+ /* Check if a prefix is present. */
>>> That should be "suffix".
[...]
+ default:
+ DBG("utils_parse_size_suffix: invalid suffix.\n");
>>> Another DBG string with a superfluous trailing '\n'.
Daniel U. Thibault
Protection des systèmes et contremesures (PSC) | Systems Protection & Countermeasures (SPC)
Cyber sécurité pour les missions essentielles (CME) | Mission Critical Cyber Security (MCCS)
R & D pour la défense Canada - Valcartier (RDDC Valcartier) | Defence R&D Canada - Valcartier (DRDC Valcartier)
2459 route de la Bravoure
Québec QC G3J 1X5
CANADA
Vox : (418) 844-4000 x4245
Fax : (418) 844-4538
NAC : 918V QSDJ <http://www.travelgis.com/map.asp?addr=918V%20QSDJ>
Gouvernement du Canada | Government of Canada
<http://www.valcartier.drdc-rddc.gc.ca/>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH lttng-tools] utils: Rework utils_parse_size_suffix
@ 2014-04-10 15:30 Simon Marchi
0 siblings, 0 replies; 7+ messages in thread
From: Simon Marchi @ 2014-04-10 15:30 UTC (permalink / raw)
To: lttng-dev
Ok, so there are a lot of problems with this function (sorry :|). Taking
the regex road is probably to complicated for nothing, so here is a
version without regexes.
I added many test cases as suggested by Sandeep Chaudhary and Daniel
Thibault. I tested on both Intel 32 and 64 bits.
Would fix #633
Signed-off-by: Simon Marchi <simon.marchi@polymtl.ca>
---
src/common/utils.c | 136 +++++++++++++-----------------
src/common/utils.h | 2 +-
tests/unit/test_utils_parse_size_suffix.c | 54 +++++++++++-
3 files changed, 111 insertions(+), 81 deletions(-)
diff --git a/src/common/utils.c b/src/common/utils.c
index 31596dd..9326080 100644
--- a/src/common/utils.c
+++ b/src/common/utils.c
@@ -28,7 +28,6 @@
#include <sys/types.h>
#include <unistd.h>
#include <inttypes.h>
-#include <regex.h>
#include <grp.h>
#include <pwd.h>
@@ -650,42 +649,10 @@ error:
return ret;
}
-/**
- * Prints the error message corresponding to a regex error code.
- *
- * @param errcode The error code.
- * @param regex The regex object that produced the error code.
- */
-static void regex_print_error(int errcode, regex_t *regex)
-{
- /* Get length of error message and allocate accordingly */
- size_t length;
- char *buffer;
-
- assert(regex != NULL);
-
- length = regerror(errcode, regex, NULL, 0);
- if (length == 0) {
- ERR("regerror returned a length of 0");
- return;
- }
-
- buffer = zmalloc(length);
- if (!buffer) {
- ERR("regex_print_error: zmalloc failed");
- return;
- }
-
- /* Get and print error message */
- regerror(errcode, regex, buffer, length);
- ERR("regex error: %s\n", buffer);
- free(buffer);
-
-}
/**
* Parse a string that represents a size in human readable format. It
- * supports decimal integers suffixed by 'k', 'M' or 'G'.
+ * supports decimal integers suffixed by 'k', 'K', 'M' or 'G'.
*
* The suffix multiply the integer by:
* 'k': 1024
@@ -693,83 +660,94 @@ static void regex_print_error(int errcode, regex_t *regex)
* 'G': 1024^3
*
* @param str The string to parse.
- * @param size Pointer to a size_t that will be filled with the
+ * @param size Pointer to a uint64_t that will be filled with the
* resulting size.
*
* @return 0 on success, -1 on failure.
*/
LTTNG_HIDDEN
-int utils_parse_size_suffix(char *str, uint64_t *size)
+int utils_parse_size_suffix(const char * const str, uint64_t * const size)
{
- regex_t regex;
int ret;
- const int nmatch = 3;
- regmatch_t suffix_match, matches[nmatch];
- unsigned long long base_size;
+ uint64_t base_size;
long shift = 0;
+ const char *str_end;
+ char *num_end;
if (!str) {
- return 0;
- }
-
- /* Compile regex */
- ret = regcomp(®ex, "^\\(0x\\)\\{0,1\\}[0-9][0-9]*\\([kKMG]\\{0,1\\}\\)$", 0);
- if (ret != 0) {
- regex_print_error(ret, ®ex);
+ DBG("utils_parse_size_suffix: received a NULL string.");
ret = -1;
goto end;
}
- /* Match regex */
- ret = regexec(®ex, str, nmatch, matches, 0);
- if (ret != 0) {
+ /* strtoull will accept a negative number, but we don't want to. */
+ if (strchr(str, '-') != NULL) {
+ DBG("utils_parse_size_suffix: invalid size string, should not contain '-'.");
ret = -1;
- goto free;
+ goto end;
}
- /* There is a match ! */
+ /* str_end will point to the \0 */
+ str_end = str + strlen(str);
errno = 0;
- base_size = strtoull(str, NULL, 0);
+ base_size = strtoull(str, &num_end, 0);
if (errno != 0) {
- PERROR("strtoull");
+ PERROR("utils_parse_size_suffix strtoull");
ret = -1;
- goto free;
+ goto end;
}
- /* Check if there is a suffix */
- suffix_match = matches[2];
- if (suffix_match.rm_eo - suffix_match.rm_so == 1) {
- switch (*(str + suffix_match.rm_so)) {
- case 'K':
- case 'k':
- shift = KIBI_LOG2;
- break;
- case 'M':
- shift = MEBI_LOG2;
- break;
- case 'G':
- shift = GIBI_LOG2;
- break;
- default:
- ERR("parse_human_size: invalid suffix");
- ret = -1;
- goto free;
- }
+ if (num_end == str) {
+ /* strtoull parsed nothing, not good. */
+ DBG("utils_parse_size_suffix: strtoull had nothing good to parse.\n");
+ ret = -1;
+ goto end;
+ }
+
+ /* Check if a prefix is present. */
+ switch (*num_end) {
+ case 'G':
+ shift = GIBI_LOG2;
+ num_end++;
+ break;
+
+ case 'M': /* */
+ shift = MEBI_LOG2;
+ num_end++;
+ break;
+
+ case 'K':
+ case 'k':
+ shift = KIBI_LOG2;
+ num_end++;
+ break;
+
+ case '\0':
+ break;
+
+ default:
+ DBG("utils_parse_size_suffix: invalid suffix.\n");
+ ret = -1;
+ goto end;
+ }
+
+ /* Check for garbage after the valid input. */
+ if (num_end != str_end) {
+ DBG("utils_parse_size_suffix: Garbage after size string.");
+ ret = -1;
+ goto end;
}
*size = base_size << shift;
/* Check for overflow */
if ((*size >> shift) != base_size) {
- ERR("parse_size_suffix: oops, overflow detected.");
+ DBG("utils_parse_size_suffix: oops, overflow detected.");
ret = -1;
- goto free;
+ goto end;
}
ret = 0;
-
-free:
- regfree(®ex);
end:
return ret;
}
diff --git a/src/common/utils.h b/src/common/utils.h
index 63290a7..b872b53 100644
--- a/src/common/utils.h
+++ b/src/common/utils.h
@@ -43,7 +43,7 @@ int utils_create_stream_file(const char *path_name, char *file_name, uint64_t si
int utils_rotate_stream_file(char *path_name, char *file_name, uint64_t size,
uint64_t count, int uid, int gid, int out_fd, uint64_t *new_count,
int *stream_fd);
-int utils_parse_size_suffix(char *str, uint64_t *size);
+int utils_parse_size_suffix(char const * const str, uint64_t * const size);
int utils_get_count_order_u32(uint32_t x);
char *utils_get_home_dir(void);
char *utils_get_user_home_dir(uid_t uid);
diff --git a/tests/unit/test_utils_parse_size_suffix.c b/tests/unit/test_utils_parse_size_suffix.c
index 990aa1b..45a87b0 100644
--- a/tests/unit/test_utils_parse_size_suffix.c
+++ b/tests/unit/test_utils_parse_size_suffix.c
@@ -43,11 +43,63 @@ static struct valid_test_input valid_tests_inputs[] = {
{ "0x1234k", 4771840 },
{ "32M", 33554432 },
{ "1024G", 1099511627776 },
+ { "0X400", 1024 },
+ { "0x40a", 1034 },
+ { "0X40b", 1035 },
+ { "0x40C", 1036 },
+ { "0X40D", 1037 },
+ { "0x40e", 1038 },
+ { "0X40f", 1039 },
+ { "00", 0 },
+ { "0k", 0 },
+ { "0K", 0 },
+ { "0M", 0 },
+ { "0G", 0 },
+ { "00k", 0 },
+ { "00K", 0 },
+ { "00M", 0 },
+ { "00G", 0 },
+ { "0x0", 0 },
+ { "0X0", 0 },
+ { "0x0k", 0 },
+ { "0X0K", 0 },
+ { "0x0M", 0 },
+ { "0X0G", 0 },
+ { "0X40G", 68719476736 },
+ { "0300k", 196608 },
+ { "0300K", 196608 },
+ { "030M", 25165824 },
+ { "020G", 17179869184 },
+ { "0xa0k", 163840 },
+ { "0xa0K", 163840 },
+ { "0XA0M", 167772160 },
+ { "0xA0G", 171798691840 },
};
static const int num_valid_tests = sizeof(valid_tests_inputs) / sizeof(valid_tests_inputs[0]);
/* Invalid test cases */
-static char *invalid_tests_inputs[] = { "", "-1", "k", "4611686018427387904G" };
+static char *invalid_tests_inputs[] = {
+ "",
+ " ",
+ "-1",
+ "k",
+ "4611686018427387904G",
+ "0x40g",
+ "08",
+ "09",
+ "0x",
+ "x0",
+ "0xx0",
+ "07kK",
+ "0xk",
+ "0XM",
+ "0xG",
+ "0x0MM",
+ "0X0GG",
+ "0a",
+ "0B",
+};
+
static const int num_invalid_tests = sizeof(invalid_tests_inputs) / sizeof(invalid_tests_inputs[0]);
static void test_utils_parse_size_suffix(void)
--
1.9.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2014-04-14 14:44 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-10 20:22 [PATCH lttng-tools] utils: Rework utils_parse_size_suffix Thibault, Daniel
[not found] <1397143819-4563-1-git-send-email-simon.marchi@polymtl.ca>
2014-04-10 19:57 ` David Goulet
[not found] ` <20140410195751.GE28773@dalia>
2014-04-10 20:14 ` Simon Marchi
2014-04-14 14:44 ` David Goulet
[not found] <48CF5AC71E61DB46B70D0F388054EFFD3599C114@VAL-E-01.valcartier.drdc-rddc.gc.ca>
2014-04-10 18:43 ` Simon Marchi
-- strict thread matches above, loose matches on Subject: below --
2014-04-10 18:31 Thibault, Daniel
2014-04-10 15:30 Simon Marchi
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.