8be66a
From bd47a98d3ce2c5e1d74deb7bc384e416a9070b96 Mon Sep 17 00:00:00 2001
8be66a
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
8be66a
Date: Thu, 9 Apr 2020 11:18:26 +0200
8be66a
Subject: [PATCH] basic/parse-util: add safe_atoux64()
8be66a
8be66a
(cherry picked from commit ce51632a357d347737bf40d3817df331cd8874cb)
8be66a
8be66a
Related: #1848373
8be66a
---
8be66a
 src/basic/parse-util.c     |  4 ++--
8be66a
 src/basic/parse-util.h     | 12 +++++++++++-
8be66a
 src/test/test-parse-util.c | 39 ++++++++++++++++++++++++++++++++++++++
8be66a
 3 files changed, 52 insertions(+), 3 deletions(-)
8be66a
8be66a
diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c
8be66a
index 056e56765e..67056c0434 100644
8be66a
--- a/src/basic/parse-util.c
8be66a
+++ b/src/basic/parse-util.c
8be66a
@@ -433,7 +433,7 @@ int safe_atoi(const char *s, int *ret_i) {
8be66a
         return 0;
8be66a
 }
8be66a
 
8be66a
-int safe_atollu(const char *s, long long unsigned *ret_llu) {
8be66a
+int safe_atollu_full(const char *s, unsigned base, long long unsigned *ret_llu) {
8be66a
         char *x = NULL;
8be66a
         unsigned long long l;
8be66a
 
8be66a
@@ -442,7 +442,7 @@ int safe_atollu(const char *s, long long unsigned *ret_llu) {
8be66a
         s += strspn(s, WHITESPACE);
8be66a
 
8be66a
         errno = 0;
8be66a
-        l = strtoull(s, &x, 0);
8be66a
+        l = strtoull(s, &x, base);
8be66a
         if (errno > 0)
8be66a
                 return -errno;
8be66a
         if (!x || x == s || *x != 0)
8be66a
diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h
8be66a
index 1fc1af7615..8a49257050 100644
8be66a
--- a/src/basic/parse-util.h
8be66a
+++ b/src/basic/parse-util.h
8be66a
@@ -33,7 +33,6 @@ static inline int safe_atou(const char *s, unsigned *ret_u) {
8be66a
 }
8be66a
 
8be66a
 int safe_atoi(const char *s, int *ret_i);
8be66a
-int safe_atollu(const char *s, unsigned long long *ret_u);
8be66a
 int safe_atolli(const char *s, long long int *ret_i);
8be66a
 
8be66a
 int safe_atou8(const char *s, uint8_t *ret);
8be66a
@@ -64,6 +63,12 @@ static inline int safe_atoi32(const char *s, int32_t *ret_i) {
8be66a
         return safe_atoi(s, (int*) ret_i);
8be66a
 }
8be66a
 
8be66a
+int safe_atollu_full(const char *s, unsigned base, long long unsigned *ret_llu);
8be66a
+
8be66a
+static inline int safe_atollu(const char *s, long long unsigned *ret_llu) {
8be66a
+        return safe_atollu_full(s, 0, ret_llu);
8be66a
+}
8be66a
+
8be66a
 static inline int safe_atou64(const char *s, uint64_t *ret_u) {
8be66a
         assert_cc(sizeof(uint64_t) == sizeof(unsigned long long));
8be66a
         return safe_atollu(s, (unsigned long long*) ret_u);
8be66a
@@ -74,6 +79,11 @@ static inline int safe_atoi64(const char *s, int64_t *ret_i) {
8be66a
         return safe_atolli(s, (long long int*) ret_i);
8be66a
 }
8be66a
 
8be66a
+static inline int safe_atoux64(const char *s, uint64_t *ret) {
8be66a
+        assert_cc(sizeof(int64_t) == sizeof(long long unsigned));
8be66a
+        return safe_atollu_full(s, 16, (long long unsigned*) ret);
8be66a
+}
8be66a
+
8be66a
 #if LONG_MAX == INT_MAX
8be66a
 static inline int safe_atolu(const char *s, unsigned long *ret_u) {
8be66a
         assert_cc(sizeof(unsigned long) == sizeof(unsigned));
8be66a
diff --git a/src/test/test-parse-util.c b/src/test/test-parse-util.c
8be66a
index e9aef5e882..8b182d9bdc 100644
8be66a
--- a/src/test/test-parse-util.c
8be66a
+++ b/src/test/test-parse-util.c
8be66a
@@ -561,6 +561,44 @@ static void test_safe_atoi64(void) {
8be66a
         assert_se(r == -EINVAL);
8be66a
 }
8be66a
 
8be66a
+static void test_safe_atoux64(void) {
8be66a
+        int r;
8be66a
+        uint64_t l;
8be66a
+
8be66a
+        r = safe_atoux64("12345", &l);
8be66a
+        assert_se(r == 0);
8be66a
+        assert_se(l == 0x12345);
8be66a
+
8be66a
+        r = safe_atoux64("  12345", &l);
8be66a
+        assert_se(r == 0);
8be66a
+        assert_se(l == 0x12345);
8be66a
+
8be66a
+        r = safe_atoux64("0x12345", &l);
8be66a
+        assert_se(r == 0);
8be66a
+        assert_se(l == 0x12345);
8be66a
+
8be66a
+        r = safe_atoux64("18446744073709551617", &l);
8be66a
+        assert_se(r == -ERANGE);
8be66a
+
8be66a
+        r = safe_atoux64("-1", &l);
8be66a
+        assert_se(r == -ERANGE);
8be66a
+
8be66a
+        r = safe_atoux64("  -1", &l);
8be66a
+        assert_se(r == -ERANGE);
8be66a
+
8be66a
+        r = safe_atoux64("junk", &l);
8be66a
+        assert_se(r == -EINVAL);
8be66a
+
8be66a
+        r = safe_atoux64("123x", &l);
8be66a
+        assert_se(r == -EINVAL);
8be66a
+
8be66a
+        r = safe_atoux64("12.3", &l);
8be66a
+        assert_se(r == -EINVAL);
8be66a
+
8be66a
+        r = safe_atoux64("", &l);
8be66a
+        assert_se(r == -EINVAL);
8be66a
+}
8be66a
+
8be66a
 static void test_safe_atod(void) {
8be66a
         int r;
8be66a
         double d;
8be66a
@@ -836,6 +874,7 @@ int main(int argc, char *argv[]) {
8be66a
         test_safe_atoux16();
8be66a
         test_safe_atou64();
8be66a
         test_safe_atoi64();
8be66a
+        test_safe_atoux64();
8be66a
         test_safe_atod();
8be66a
         test_parse_percent();
8be66a
         test_parse_percent_unbounded();