]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: strnum - Add str_parse_data_uintmax()
authorStephan Bosch <stephan.bosch@open-xchange.com>
Wed, 1 Oct 2025 20:49:22 +0000 (22:49 +0200)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Thu, 9 Oct 2025 08:41:22 +0000 (08:41 +0000)
Allows parsing numbers from generic data, rather than nul-terminated C-strings.

src/lib/strnum.c
src/lib/strnum.h
src/lib/test-strnum.c

index 489b9c2b09f956b4d89db8f245766d296a4d14a6..c16cfe017add21e1423a244976c953b5bc81d49d 100644 (file)
@@ -79,30 +79,36 @@ STR_TO_U__TEMPLATE(str_to_ullong, unsigned long long)
 STR_TO_U__TEMPLATE(str_to_uint32, uint32_t)
 STR_TO_U__TEMPLATE(str_to_uint64, uint64_t)
 
-int str_parse_uintmax(const char *str, uintmax_t *num_r,
-       const char **endp_r)
+int str_parse_data_uintmax(const unsigned char *data, size_t size,
+                          uintmax_t *num_r, const unsigned char **endp_r)
 {
+       const unsigned char *p = data, *pend = data + size;
        uintmax_t n = 0;
 
-       if (*str < '0' || *str > '9')
+       if (p >= pend || *p < '0' || *p > '9')
                return -1;
 
        do {
                if (n >= ((uintmax_t)-1 / 10)) {
                        if (n > (uintmax_t)-1 / 10)
                                return -1;
-                       if ((uintmax_t)(*str - '0') > ((uintmax_t)-1 % 10))
+                       if ((uintmax_t)(*p - '0') > ((uintmax_t)-1 % 10))
                                return -1;
                }
-               n = n * 10 + (*str - '0');
-               str++;
-       } while (*str >= '0' && *str <= '9');
+               n = n * 10 + (*p - '0');
+               p++;
+       } while (p < pend && *p >= '0' && *p <= '9');
 
        if (endp_r != NULL)
-               *endp_r = str;
+               *endp_r = p;
        *num_r = n;
        return 0;
 }
+int str_parse_uintmax(const char *str, uintmax_t *num_r, const char **endp_r)
+{
+       return str_parse_data_uintmax((const unsigned char *)str, strlen(str),
+                                     num_r, (const unsigned char **)endp_r);
+}
 int str_to_uintmax(const char *str, uintmax_t *num_r)
 {
        const char *endp;
index 2fc684c3bf11913605659e8d7153369d1aa60a2e..82d3b3b2c92f1965cc5c73a765c2c7ec624eef91 100644 (file)
@@ -42,6 +42,9 @@ int str_to_uintmax(const char *str, uintmax_t *num_r)
        ATTR_WARN_UNUSED_RESULT;
 int str_parse_uintmax(const char *str, uintmax_t *num_r,
        const char **endp_r) ATTR_WARN_UNUSED_RESULT ATTR_NULL(3);
+int str_parse_data_uintmax(const unsigned char *data, size_t size,
+                          uintmax_t *num_r, const unsigned char **endp_r)
+       ATTR_WARN_UNUSED_RESULT;
 
 /* Returns TRUE if str is a valid unsigned number that equals num. */
 bool str_uint_equals(const char *str, uintmax_t num);
index 3df2bff752bc4cf7c75b2e2a1a80f0e37a66311b..51fbb2c6b53290556ab1a83bcf1e9700933f7953 100644 (file)
@@ -46,7 +46,8 @@ static void test_str_to_uintmax(void)
                test_assert_idx(value == value_back, i);
 
                /* test with trailing noise */
-               buff[len] = 'x'; /* don't even null-terminate, let's be evil */
+               buff[len] = 'x';
+               buff[len + 1] = '\0';
                value_back = 0x1234567890123456;
                ret = str_to_uintmax(buff, &value_back);
                test_assert_idx(ret < 0, i);