]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
boot: Add parse_number8/16
authorJan Janssen <medhefgo@web.de>
Wed, 1 Jun 2022 11:35:29 +0000 (13:35 +0200)
committerJan Janssen <medhefgo@web.de>
Fri, 10 Jun 2022 09:50:13 +0000 (11:50 +0200)
src/boot/efi/efi-string.c
src/boot/efi/efi-string.h
src/boot/efi/test-efi-string.c

index b9ef1548ca24494fe21ab6b1c460905a60aebc97..b1d83cb483f483328c0268e29c8a4b8169431241 100644 (file)
@@ -239,6 +239,38 @@ bool efi_fnmatch(const char16_t *pattern, const char16_t *haystack) {
         return efi_fnmatch_internal(pattern, haystack, 32);
 }
 
+#define DEFINE_PARSE_NUMBER(type, name)                                    \
+        bool name(const type *s, uint64_t *ret_u, const type **ret_tail) { \
+                assert(ret_u);                                             \
+                                                                           \
+                if (!s)                                                    \
+                        return false;                                      \
+                                                                           \
+                /* Need at least one digit. */                             \
+                if (*s < '0' || *s > '9')                                  \
+                        return false;                                      \
+                                                                           \
+                uint64_t u = 0;                                            \
+                while (*s >= '0' && *s <= '9') {                           \
+                        if (__builtin_mul_overflow(u, 10, &u))             \
+                                return false;                              \
+                        if (__builtin_add_overflow(u, *s - '0', &u))       \
+                                return false;                              \
+                        s++;                                               \
+                }                                                          \
+                                                                           \
+                if (!ret_tail && *s != '\0')                               \
+                        return false;                                      \
+                                                                           \
+                *ret_u = u;                                                \
+                if (ret_tail)                                              \
+                        *ret_tail = s;                                     \
+                return true;                                               \
+        }
+
+DEFINE_PARSE_NUMBER(char, parse_number8);
+DEFINE_PARSE_NUMBER(char16_t, parse_number16);
+
 int efi_memcmp(const void *p1, const void *p2, size_t n) {
         const uint8_t *up1 = p1, *up2 = p2;
         int r;
index 55c9c6e47ad7224b2e2abee91ae6da956641511f..c25349c0e1e2ce607cdda946c426608c78dc72cc 100644 (file)
@@ -101,6 +101,9 @@ static inline char16_t *xstrdup16(const char16_t *s) {
 
 bool efi_fnmatch(const char16_t *pattern, const char16_t *haystack);
 
+bool parse_number8(const char *s, uint64_t *ret_u, const char **ret_tail);
+bool parse_number16(const char16_t *s, uint64_t *ret_u, const char16_t **ret_tail);
+
 #ifdef SD_BOOT
 /* The compiler normally has knowledge about standard functions such as memcmp, but this is not the case when
  * compiling with -ffreestanding. By referring to builtins, the compiler can check arguments and do
index 178ad766cb460675aff6ceb065351fc89cc77ebb..0bfb564e3d66fca4704fbacf1bc1ebdfb21df671 100644 (file)
@@ -371,6 +371,60 @@ TEST(efi_fnmatch) {
         TEST_FNMATCH_ONE("?a*b[.-0]c", "/a/b/c", true);
 }
 
+TEST(parse_number8) {
+        uint64_t u;
+        const char *tail;
+
+        assert_se(!parse_number8(NULL, &u, NULL));
+        assert_se(!parse_number8("", &u, NULL));
+        assert_se(!parse_number8("a1", &u, NULL));
+        assert_se(!parse_number8("1a", &u, NULL));
+        assert_se(!parse_number8("-42", &u, NULL));
+        assert_se(!parse_number8("18446744073709551616", &u, NULL));
+
+        assert_se(parse_number8("0", &u, NULL));
+        assert_se(u == 0);
+        assert_se(parse_number8("1", &u, NULL));
+        assert_se(u == 1);
+        assert_se(parse_number8("999", &u, NULL));
+        assert_se(u == 999);
+        assert_se(parse_number8("18446744073709551615", &u, NULL));
+        assert_se(u == UINT64_MAX);
+        assert_se(parse_number8("42", &u, &tail));
+        assert_se(u == 42);
+        assert_se(streq8(tail, ""));
+        assert_se(parse_number8("54321rest", &u, &tail));
+        assert_se(u == 54321);
+        assert_se(streq8(tail, "rest"));
+}
+
+TEST(parse_number16) {
+        uint64_t u;
+        const char16_t *tail;
+
+        assert_se(!parse_number16(NULL, &u, NULL));
+        assert_se(!parse_number16(u"", &u, NULL));
+        assert_se(!parse_number16(u"a1", &u, NULL));
+        assert_se(!parse_number16(u"1a", &u, NULL));
+        assert_se(!parse_number16(u"-42", &u, NULL));
+        assert_se(!parse_number16(u"18446744073709551616", &u, NULL));
+
+        assert_se(parse_number16(u"0", &u, NULL));
+        assert_se(u == 0);
+        assert_se(parse_number16(u"1", &u, NULL));
+        assert_se(u == 1);
+        assert_se(parse_number16(u"999", &u, NULL));
+        assert_se(u == 999);
+        assert_se(parse_number16(u"18446744073709551615", &u, NULL));
+        assert_se(u == UINT64_MAX);
+        assert_se(parse_number16(u"42", &u, &tail));
+        assert_se(u == 42);
+        assert_se(streq16(tail, u""));
+        assert_se(parse_number16(u"54321rest", &u, &tail));
+        assert_se(u == 54321);
+        assert_se(streq16(tail, u"rest"));
+}
+
 TEST(efi_memcmp) {
         assert_se(efi_memcmp(NULL, NULL, 0) == 0);
         assert_se(efi_memcmp(NULL, NULL, 1) == 0);