[PATCH 3/4] util: Use g_ascii_strtoll

Martin Kletzander mkletzan at redhat.com
Mon Jun 12 07:55:36 UTC 2023


This has two main advantages:

- it parses the number with C locale explicitly

- it behaves the same on Windows as on Linux and BSD

both of which are wanted behaviours.

Signed-off-by: Martin Kletzander <mkletzan at redhat.com>
---
 src/util/virstring.c | 54 +++++++++++++++++++++++++++-----------------
 1 file changed, 33 insertions(+), 21 deletions(-)

diff --git a/src/util/virstring.c b/src/util/virstring.c
index 635685eed4a4..6b728ff04759 100644
--- a/src/util/virstring.c
+++ b/src/util/virstring.c
@@ -35,7 +35,7 @@
 
 VIR_LOG_INIT("util.string");
 
-/* Like strtol, but produce an "int" result, and check more carefully.
+/* Like strtol with C locale, but produce an "int" result, and check more carefully.
    Return 0 upon success;  return -1 to indicate failure.
    When END_PTR is NULL, the byte after the final valid digit must be NUL.
    Otherwise, it's like strtol and lets the caller check any suffix for
@@ -44,12 +44,12 @@ VIR_LOG_INIT("util.string");
 int
 virStrToLong_i(char const *s, char **end_ptr, int base, int *result)
 {
-    long int val;
+    long long val;
     char *p;
     int err;
 
     errno = 0;
-    val = strtol(s, &p, base); /* exempt from syntax-check */
+    val = g_ascii_strtoll(s, &p, base);
     err = (errno || (!end_ptr && *p) || p == s || (int) val != val);
     if (end_ptr)
         *end_ptr = p;
@@ -65,22 +65,22 @@ virStrToLong_i(char const *s, char **end_ptr, int base, int *result)
 int
 virStrToLong_ui(char const *s, char **end_ptr, int base, unsigned int *result)
 {
-    unsigned long int val;
+    unsigned long long val;
     char *p;
     bool err = false;
 
     errno = 0;
-    val = strtoul(s, &p, base); /* exempt from syntax-check */
+    val = g_ascii_strtoull(s, &p, base);
 
     /* This one's tricky.  We _want_ to allow "-1" as shorthand for
      * UINT_MAX regardless of whether long is 32-bit or 64-bit.  But
-     * strtoul treats "-1" as ULONG_MAX, and going from ulong back
-     * to uint differs depending on the size of long. */
-    if (sizeof(long) > sizeof(int) && memchr(s, '-', p - s)) {
+     * g_ascii_strtoull treats "-1" as ULLONG_MAX, and going from ullong back
+     * to uint differs depending on the size of uint. */
+    if (memchr(s, '-', p - s)) {
         if (-val > UINT_MAX)
             err = true;
         else
-            val &= 0xffffffff;
+            val &= UINT_MAX;
     }
 
     err |= (errno || (!end_ptr && *p) || p == s || (unsigned int) val != val);
@@ -97,12 +97,12 @@ virStrToLong_ui(char const *s, char **end_ptr, int base, unsigned int *result)
 int
 virStrToLong_uip(char const *s, char **end_ptr, int base, unsigned int *result)
 {
-    unsigned long int val;
+    unsigned long long val;
     char *p;
     bool err = false;
 
     errno = 0;
-    val = strtoul(s, &p, base); /* exempt from syntax-check */
+    val = g_ascii_strtoull(s, &p, base);
     err = (memchr(s, '-', p - s) ||
            errno || (!end_ptr && *p) || p == s || (unsigned int) val != val);
     if (end_ptr)
@@ -121,13 +121,25 @@ virStrToLong_uip(char const *s, char **end_ptr, int base, unsigned int *result)
 int
 virStrToLong_ul(char const *s, char **end_ptr, int base, unsigned long *result)
 {
-    unsigned long int val;
+    unsigned long long val;
     char *p;
-    int err;
+    bool err = false;
 
     errno = 0;
-    val = strtoul(s, &p, base); /* exempt from syntax-check */
-    err = (errno || (!end_ptr && *p) || p == s);
+    val = g_ascii_strtoull(s, &p, base);
+
+    /* This one's tricky.  We _want_ to allow "-1" as shorthand for
+     * ULONG_MAX regardless of whether long is 32-bit or 64-bit.  But
+     * g_ascii_strtoull treats "-1" as ULLONG_MAX, and going from ullong back
+     * to ulong differs depending on the size of ulong. */
+    if (memchr(s, '-', p - s)) {
+        if (-val > ULONG_MAX)
+            err = true;
+        else
+            val &= ULONG_MAX;
+    }
+
+    err |= (errno || (!end_ptr && *p) || p == s || (unsigned long) val != val);
     if (end_ptr)
         *end_ptr = p;
     if (err)
@@ -142,14 +154,14 @@ int
 virStrToLong_ulp(char const *s, char **end_ptr, int base,
                  unsigned long *result)
 {
-    unsigned long int val;
+    unsigned long long val;
     char *p;
     int err;
 
     errno = 0;
-    val = strtoul(s, &p, base); /* exempt from syntax-check */
+    val = g_ascii_strtoull(s, &p, base);
     err = (memchr(s, '-', p - s) ||
-           errno || (!end_ptr && *p) || p == s);
+           errno || (!end_ptr && *p) || p == s || (unsigned long) val != val);
     if (end_ptr)
         *end_ptr = p;
     if (err)
@@ -167,7 +179,7 @@ virStrToLong_ll(char const *s, char **end_ptr, int base, long long *result)
     int err;
 
     errno = 0;
-    val = strtoll(s, &p, base); /* exempt from syntax-check */
+    val = g_ascii_strtoll(s, &p, base);
     err = (errno || (!end_ptr && *p) || p == s);
     if (end_ptr)
         *end_ptr = p;
@@ -189,7 +201,7 @@ virStrToLong_ull(char const *s, char **end_ptr, int base,
     int err;
 
     errno = 0;
-    val = strtoull(s, &p, base); /* exempt from syntax-check */
+    val = g_ascii_strtoull(s, &p, base);
     err = (errno || (!end_ptr && *p) || p == s);
     if (end_ptr)
         *end_ptr = p;
@@ -210,7 +222,7 @@ virStrToLong_ullp(char const *s, char **end_ptr, int base,
     int err;
 
     errno = 0;
-    val = strtoull(s, &p, base); /* exempt from syntax-check */
+    val = g_ascii_strtoull(s, &p, base);
     err = (memchr(s, '-', p - s) ||
            errno || (!end_ptr && *p) || p == s);
     if (end_ptr)
-- 
2.41.0



More information about the libvir-list mailing list