boot: Add parse_number8/16

This commit is contained in:
Jan Janssen
2022-06-10 11:50:13 +02:00
parent 67bca872ea
commit 72bd3458e5
3 changed files with 89 additions and 0 deletions
+32
View 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;
+3
View 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
+54
View 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);