diff options
author | Jes Klinke <jbk@google.com> | 2019-05-08 10:31:57 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2019-05-14 20:13:39 -0700 |
commit | ac8a13329b0b321daeb87f6afb79c163beb21372 (patch) | |
tree | 386987b4a5b057501dc72463333b32a23f8f38aa | |
parent | a823e6d96f28928d5808149c51cd8f4963b4880e (diff) | |
download | chrome-ec-ac8a13329b0b321daeb87f6afb79c163beb21372.tar.gz |
Align behavior of strtoi() and strtoul() to match Linux manpage description of strtol().
Behavior changes:
1) Initial '+' character is tolerated.
2) Hexadecimal strings prefixed with "0x" are rejected, if given base
parameter is anything other than 16 or 0, rather than parsed as hex,
diregarding the given base.
3) If given base is 0, strings starting with leading zero will be parsed
as octal, rather than decimal.
4) Initial '-' character allowed before "0x" on hexadecimal numbers.
(Note: This is my first time using git or gerrit, please let me know if there is
some policy or customs that I am not properly adhering to.)
BRANCH=none
TEST=make run-utils_str V=1
Bug: 940329
Change-Id: I71654471b77f0df071a58ff6bed7028f00cd46b5
Signed-off-by: Jes Bodi Klinke <jbk@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1577750
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Tested-by: Jes Klinke <jbk@chromium.org>
Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
-rw-r--r-- | common/util.c | 59 | ||||
-rw-r--r-- | test/utils_str.c | 97 |
2 files changed, 128 insertions, 28 deletions
diff --git a/common/util.c b/common/util.c index 8005e0bfdb..f3d3fc3993 100644 --- a/common/util.c +++ b/common/util.c @@ -115,6 +115,18 @@ int atoi(const char *nptr) return neg ? -result : result; } +static int find_base(int base, int *c, const char **nptr) { + if ((base == 0 || base == 16) && *c == '0' + && (**nptr == 'x' || **nptr == 'X')) { + *c = (*nptr)[1]; + (*nptr) += 2; + base = 16; + } else if (base == 0) { + base = *c == '0' ? 8 : 10; + } + return base; +} + /* Like strtol(), but for integers */ int strtoi(const char *nptr, char **endptr, int base) @@ -123,24 +135,18 @@ int strtoi(const char *nptr, char **endptr, int base) int neg = 0; int c = '\0'; - if (endptr) - *endptr = (char *)nptr; - while ((c = *nptr++) && isspace(c)) ; - if (c == '0' && *nptr == 'x') { - base = 16; - c = nptr[1]; - nptr += 2; - } else if (base == 0) { - base = 10; - if (c == '-') { - neg = 1; - c = *nptr++; - } + if (c == '+') { + c = *nptr++; + } else if (c == '-') { + neg = 1; + c = *nptr++; } + base = find_base(base, &c, &nptr); + while (c) { if (c >= '0' && c < '0' + MIN(base, 10)) result = result * base + (c - '0'); @@ -151,11 +157,11 @@ int strtoi(const char *nptr, char **endptr, int base) else break; - if (endptr) - *endptr = (char *)nptr; c = *nptr++; } + if (endptr) + *endptr = (char *)nptr - 1; return neg ? -result : result; } @@ -164,21 +170,18 @@ uint64_t strtoul(const char *nptr, char **endptr, int base) uint64_t result = 0; int c = '\0'; - if (endptr) - *endptr = (char *)nptr; - while ((c = *nptr++) && isspace(c)) ; - if (c == '0' && *nptr == 'x') { - base = 16; - c = nptr[1]; - nptr += 2; - } else if (base == 0) { - base = 10; - if (c == '-') - return result; + if (c == '+') { + c = *nptr++; + } else if (c == '-') { + if (endptr) + *endptr = (char *)nptr - 1; + return result; } + + base = find_base(base, &c, &nptr); while (c) { if (c >= '0' && c < '0' + MIN(base, 10)) @@ -190,11 +193,11 @@ uint64_t strtoul(const char *nptr, char **endptr, int base) else break; - if (endptr) - *endptr = (char *)nptr; c = *nptr++; } + if (endptr) + *endptr = (char *)nptr - 1; return result; } diff --git a/test/utils_str.c b/test/utils_str.c index 81c600bc03..6498ef85d5 100644 --- a/test/utils_str.c +++ b/test/utils_str.c @@ -33,16 +33,112 @@ static int test_strtoi(void) TEST_ASSERT(strtoi("10", &e, 0) == 10); TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoi("010", &e, 0) == 8); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoi("+010", &e, 0) == 8); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoi("-010", &e, 0) == -8); + TEST_ASSERT(e && (*e == '\0')); TEST_ASSERT(strtoi("0x1f z", &e, 0) == 31); TEST_ASSERT(e && (*e == ' ')); + TEST_ASSERT(strtoi("0X1f z", &e, 0) == 31); + TEST_ASSERT(e && (*e == ' ')); TEST_ASSERT(strtoi("10a", &e, 16) == 266); TEST_ASSERT(e && (*e == '\0')); TEST_ASSERT(strtoi("0x02C", &e, 16) == 44); TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoi("+0x02C", &e, 16) == 44); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoi("-0x02C", &e, 16) == -44); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoi("0x02C", &e, 0) == 44); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoi("+0x02C", &e, 0) == 44); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoi("-0x02C", &e, 0) == -44); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoi("0X02C", &e, 16) == 44); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoi("+0X02C", &e, 16) == 44); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoi("-0X02C", &e, 16) == -44); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoi("0X02C", &e, 0) == 44); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoi("+0X02C", &e, 0) == 44); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoi("-0X02C", &e, 0) == -44); + TEST_ASSERT(e && (*e == '\0')); TEST_ASSERT(strtoi(" -12", &e, 0) == -12); TEST_ASSERT(e && (*e == '\0')); TEST_ASSERT(strtoi("!", &e, 0) == 0); TEST_ASSERT(e && (*e == '!')); + TEST_ASSERT(strtoi("+!", &e, 0) == 0); + TEST_ASSERT(e && (*e == '!')); + TEST_ASSERT(strtoi("+0!", &e, 0) == 0); + TEST_ASSERT(e && (*e == '!')); + TEST_ASSERT(strtoi("+0x!", &e, 0) == 0); + TEST_ASSERT(e && (*e == '!')); + TEST_ASSERT(strtoi("+0X!", &e, 0) == 0); + TEST_ASSERT(e && (*e == '!')); + + return EC_SUCCESS; +} + +static int test_strtoul(void) +{ + char *e; + + TEST_ASSERT(strtoul("10", &e, 0) == 10); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoul("010", &e, 0) == 8); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoul("+010", &e, 0) == 8); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoul("-010", &e, 0) == 0); + TEST_ASSERT(e && (*e == '-')); + TEST_ASSERT(strtoul("0x1f z", &e, 0) == 31); + TEST_ASSERT(e && (*e == ' ')); + TEST_ASSERT(strtoul("0X1f z", &e, 0) == 31); + TEST_ASSERT(e && (*e == ' ')); + TEST_ASSERT(strtoul("10a", &e, 16) == 266); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoul("0x02C", &e, 16) == 44); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoul("+0x02C", &e, 16) == 44); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoul("-0x02C", &e, 16) == 0); + TEST_ASSERT(e && (*e == '-')); + TEST_ASSERT(strtoul("0x02C", &e, 0) == 44); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoul("+0x02C", &e, 0) == 44); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoul("-0x02C", &e, 0) == 0); + TEST_ASSERT(e && (*e == '-')); + TEST_ASSERT(strtoul("0X02C", &e, 16) == 44); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoul("+0X02C", &e, 16) == 44); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoul("-0X02C", &e, 16) == 0); + TEST_ASSERT(e && (*e == '-')); + TEST_ASSERT(strtoul("0X02C", &e, 0) == 44); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoul("+0X02C", &e, 0) == 44); + TEST_ASSERT(e && (*e == '\0')); + TEST_ASSERT(strtoul("-0X02C", &e, 0) == 0); + TEST_ASSERT(e && (*e == '-')); + TEST_ASSERT(strtoul(" -12", &e, 0) == 0); + TEST_ASSERT(e && (*e == '-')); + TEST_ASSERT(strtoul("!", &e, 0) == 0); + TEST_ASSERT(e && (*e == '!')); + TEST_ASSERT(strtoul("+!", &e, 0) == 0); + TEST_ASSERT(e && (*e == '!')); + TEST_ASSERT(strtoul("+0!", &e, 0) == 0); + TEST_ASSERT(e && (*e == '!')); + TEST_ASSERT(strtoul("+0x!", &e, 0) == 0); + TEST_ASSERT(e && (*e == '!')); + TEST_ASSERT(strtoul("+0X!", &e, 0) == 0); + TEST_ASSERT(e && (*e == '!')); return EC_SUCCESS; } @@ -157,6 +253,7 @@ void run_test(void) RUN_TEST(test_isalpha); RUN_TEST(test_isprint); RUN_TEST(test_strtoi); + RUN_TEST(test_strtoul); RUN_TEST(test_parse_bool); RUN_TEST(test_strzcpy); RUN_TEST(test_strncpy); |