From: Stephan Bosch Date: Wed, 1 Oct 2025 20:49:22 +0000 (+0200) Subject: lib: strnum - Add str_parse_data_uintmax() X-Git-Tag: 2.4.2~353 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9503ecea183b9670323b76bed2fa1c5a93d28018;p=thirdparty%2Fdovecot%2Fcore.git lib: strnum - Add str_parse_data_uintmax() Allows parsing numbers from generic data, rather than nul-terminated C-strings. --- diff --git a/src/lib/strnum.c b/src/lib/strnum.c index 489b9c2b09..c16cfe017a 100644 --- a/src/lib/strnum.c +++ b/src/lib/strnum.c @@ -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; diff --git a/src/lib/strnum.h b/src/lib/strnum.h index 2fc684c3bf..82d3b3b2c9 100644 --- a/src/lib/strnum.h +++ b/src/lib/strnum.h @@ -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); diff --git a/src/lib/test-strnum.c b/src/lib/test-strnum.c index 3df2bff752..51fbb2c6b5 100644 --- a/src/lib/test-strnum.c +++ b/src/lib/test-strnum.c @@ -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);