[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v3 08/19] cutils: Allow NULL endptr in parse_uint()
From: |
Eric Blake |
Subject: |
[PATCH v3 08/19] cutils: Allow NULL endptr in parse_uint() |
Date: |
Mon, 22 May 2023 14:04:30 -0500 |
All the qemu_strto*() functions permit a NULL endptr, just like their
libc counterparts, leaving parse_uint() as the oddball that caused
SEGFAULT on NULL and required the user to call parse_uint_full()
instead. Relax things for consistency, even though the testsuite is
the only impacted caller. Add one more unit test to ensure even
parse_uint_full(NULL, 0, &value) works. This also fixes our code to
uniformly favor EINVAL over ERANGE when both apply.
Also fixes a doc mismatch @v vs. a parameter named value.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
---
v3: commit message tweak, R-b added
---
tests/unit/test-cutils.c | 18 ++++++++++++++++--
util/cutils.c | 34 ++++++++++++----------------------
2 files changed, 28 insertions(+), 24 deletions(-)
diff --git a/tests/unit/test-cutils.c b/tests/unit/test-cutils.c
index 70469b583d3..2ac96117995 100644
--- a/tests/unit/test-cutils.c
+++ b/tests/unit/test-cutils.c
@@ -270,14 +270,26 @@ static void test_parse_uint_full_correct(void)
static void test_parse_uint_full_erange_junk(void)
{
- /* FIXME - inconsistent with qemu_strto* which favors EINVAL */
+ /* EINVAL has priority over ERANGE */
uint64_t i = 999;
const char *str = "-2junk";
int r;
r = parse_uint_full(str, 0, &i);
- g_assert_cmpint(r, ==, -ERANGE /* FIXME -EINVAL */);
+ g_assert_cmpint(r, ==, -EINVAL);
+ g_assert_cmpuint(i, ==, 0);
+}
+
+static void test_parse_uint_full_null(void)
+{
+ uint64_t i = 999;
+ const char *str = NULL;
+ int r;
+
+ r = parse_uint_full(str, 0, &i);
+
+ g_assert_cmpint(r, ==, -EINVAL);
g_assert_cmpuint(i, ==, 0);
}
@@ -3328,6 +3340,8 @@ int main(int argc, char **argv)
test_parse_uint_full_correct);
g_test_add_func("/cutils/parse_uint_full/erange_junk",
test_parse_uint_full_erange_junk);
+ g_test_add_func("/cutils/parse_uint_full/null",
+ test_parse_uint_full_null);
/* qemu_strtoi() tests */
g_test_add_func("/cutils/qemu_strtoi/correct",
diff --git a/util/cutils.c b/util/cutils.c
index 0e279a531aa..56a2aced8d4 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -722,8 +722,7 @@ const char *qemu_strchrnul(const char *s, int c)
* parse_uint:
*
* @s: String to parse
- * @endptr: Destination for pointer to first character not consumed, must
- * not be %NULL
+ * @endptr: Destination for pointer to first character not consumed
* @base: integer base, between 2 and 36 inclusive, or 0
* @value: Destination for parsed integer value
*
@@ -737,7 +736,8 @@ const char *qemu_strchrnul(const char *s, int c)
*
* Set *@endptr to point right beyond the parsed integer (even if the integer
* overflows or is negative, all digits will be parsed and *@endptr will
- * point right beyond them).
+ * point right beyond them). If @endptr is %NULL, any trailing character
+ * instead causes a result of -EINVAL with *@value of 0.
*
* If the integer is negative, set *@value to 0, and return -ERANGE.
* (If you want to allow negative numbers that wrap around within
@@ -784,7 +784,12 @@ int parse_uint(const char *s, const char **endptr, int
base, uint64_t *value)
out:
*value = val;
- *endptr = endp;
+ if (endptr) {
+ *endptr = endp;
+ } else if (s && *endp) {
+ r = -EINVAL;
+ *value = 0;
+ }
return r;
}
@@ -795,28 +800,13 @@ out:
* @base: integer base, between 2 and 36 inclusive, or 0
* @value: Destination for parsed integer value
*
- * Parse unsigned integer from entire string
+ * Parse unsigned integer from entire string, rejecting any trailing slop.
*
- * Have the same behavior of parse_uint(), but with an additional
- * check for additional data after the parsed number. If extra
- * characters are present after a non-overflowing parsed number, the
- * function will return -EINVAL, and *@v will be set to 0.
+ * Shorthand for parse_uint(s, NULL, base, value).
*/
int parse_uint_full(const char *s, int base, uint64_t *value)
{
- const char *endp;
- int r;
-
- r = parse_uint(s, &endp, base, value);
- if (r < 0) {
- return r;
- }
- if (*endp) {
- *value = 0;
- return -EINVAL;
- }
-
- return 0;
+ return parse_uint(s, NULL, base, value);
}
int qemu_parse_fd(const char *param)
--
2.40.1
- Re: [PATCH v3 04/19] test-cutils: Test more integer corner cases, (continued)
- [PATCH v3 06/19] cutils: Document differences between parse_uint and qemu_strtou64, Eric Blake, 2023/05/22
- [PATCH v3 01/19] test-cutils: Avoid g_assert in unit tests, Eric Blake, 2023/05/22
- [PATCH v3 02/19] test-cutils: Use g_assert_cmpuint where appropriate, Eric Blake, 2023/05/22
- [PATCH v3 07/19] cutils: Adjust signature of parse_uint[_full], Eric Blake, 2023/05/22
- [PATCH v3 14/19] test-cutils: Add more coverage to qemu_strtosz, Eric Blake, 2023/05/22
- [PATCH v3 03/19] test-cutils: Test integral qemu_strto* value on failures, Eric Blake, 2023/05/22
- [PATCH v3 05/19] cutils: Fix wraparound parsing in qemu_strtoui, Eric Blake, 2023/05/22
- [PATCH v3 08/19] cutils: Allow NULL endptr in parse_uint(),
Eric Blake <=
- [PATCH v3 09/19] test-cutils: Add coverage of qemu_strtod, Eric Blake, 2023/05/22
- [PATCH v3 16/19] cutils: Set value in all integral qemu_strto* error paths, Eric Blake, 2023/05/22
- [PATCH v3 10/19] test-cutils: Prepare for upcoming semantic change in qemu_strtosz, Eric Blake, 2023/05/22
- [PATCH v3 12/19] cutils: Allow NULL str in qemu_strtosz, Eric Blake, 2023/05/22
- [PATCH v3 11/19] test-cutils: Refactor qemu_strtosz tests for less boilerplate, Eric Blake, 2023/05/22
- [PATCH v3 13/19] numa: Check for qemu_strtosz_MiB error, Eric Blake, 2023/05/22
- [PATCH v3 17/19] cutils: Use parse_uint in qemu_strtosz for negative rejection, Eric Blake, 2023/05/22
- [PATCH v3 15/19] cutils: Set value in all qemu_strtosz* error paths, Eric Blake, 2023/05/22
- [PATCH v3 18/19] cutils: Improve qemu_strtod* error paths, Eric Blake, 2023/05/22
- [PATCH v3 19/19] cutils: Improve qemu_strtosz handling of fractions, Eric Blake, 2023/05/22