summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJes Klinke <jbk@google.com>2019-05-08 10:31:57 -0700
committerchrome-bot <chrome-bot@chromium.org>2019-05-14 20:13:39 -0700
commitac8a13329b0b321daeb87f6afb79c163beb21372 (patch)
tree386987b4a5b057501dc72463333b32a23f8f38aa
parenta823e6d96f28928d5808149c51cd8f4963b4880e (diff)
downloadchrome-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.c59
-rw-r--r--test/utils_str.c97
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);