From: Jan Janssen Date: Wed, 25 May 2022 08:59:01 +0000 (+0200) Subject: boot: Add xstrdup8/16 X-Git-Tag: v252-rc1~892^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=101f68ff331e47a8f8ddc2313661669afda5af30;p=thirdparty%2Fsystemd.git boot: Add xstrdup8/16 --- diff --git a/src/boot/efi/cpio.c b/src/boot/efi/cpio.c index 8345f957f7e..18689d9d6b7 100644 --- a/src/boot/efi/cpio.c +++ b/src/boot/efi/cpio.c @@ -255,7 +255,7 @@ static EFI_STATUS pack_cpio_prefix( if (e > p) { _cleanup_freepool_ CHAR8 *t = NULL; - t = xstrndup8(path, e - path); + t = (CHAR8 *) xstrndup8((const char *) path, e - path); if (!t) return EFI_OUT_OF_RESOURCES; diff --git a/src/boot/efi/efi-string.c b/src/boot/efi/efi-string.c index 1626ccf2049..b93d0ed46a5 100644 --- a/src/boot/efi/efi-string.c +++ b/src/boot/efi/efi-string.c @@ -5,6 +5,15 @@ #include "efi-string.h" +#ifdef SD_BOOT +# include "util.h" +# define xmalloc(n) xallocate_pool(n) +#else +# include +# include "macro.h" +# define xmalloc(n) ASSERT_SE_PTR(malloc(n)) +#endif + /* String functions for both char and char16_t that should behave the same way as their respective * counterpart in userspace. Where it makes sense, these accept NULL and do something sensible whereas * userspace does not allow for this (strlen8(NULL) returns 0 like strlen_ptr(NULL) for example). To make it @@ -138,6 +147,32 @@ DEFINE_STRCPY(char16_t, strcpy16); DEFINE_STRCHR(char, strchr8); DEFINE_STRCHR(char16_t, strchr16); +#define DEFINE_STRNDUP(type, name, len_func) \ + type *name(const type *s, size_t n) { \ + if (!s) \ + return NULL; \ + \ + size_t len = len_func(s, n); \ + size_t size = len * sizeof(type); \ + \ + type *dup = xmalloc(size + sizeof(type)); \ + efi_memcpy(dup, s, size); \ + dup[len] = '\0'; \ + \ + return dup; \ + } + +DEFINE_STRNDUP(char, xstrndup8, strnlen8); +DEFINE_STRNDUP(char16_t, xstrndup16, strnlen16); + +char *xstrdup8(const char *s) { + return xstrndup8(s, SIZE_MAX); +} + +char16_t *xstrdup16(const char16_t *s) { + return xstrndup16(s, SIZE_MAX); +} + int efi_memcmp(const void *p1, const void *p2, size_t n) { if (!p1 || !p2) return CMP(p1, p2); diff --git a/src/boot/efi/efi-string.h b/src/boot/efi/efi-string.h index 79d81040221..c203c63c550 100644 --- a/src/boot/efi/efi-string.h +++ b/src/boot/efi/efi-string.h @@ -74,6 +74,12 @@ char16_t *strcpy16(char16_t * restrict dest, const char16_t * restrict src); char *strchr8(const char *s, char c); char16_t *strchr16(const char16_t *s, char16_t c); +char *xstrndup8(const char *s, size_t n); +char16_t *xstrndup16(const char16_t *s, size_t n); + +char *xstrdup8(const char *s); +char16_t *xstrdup16(const char16_t *s); + #ifdef SD_BOOT /* The compiler normaly 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 diff --git a/src/boot/efi/test-efi-string.c b/src/boot/efi/test-efi-string.c index 087f9d7e995..d5044d801c7 100644 --- a/src/boot/efi/test-efi-string.c +++ b/src/boot/efi/test-efi-string.c @@ -240,6 +240,88 @@ TEST(strchr16) { assert_se(strchr16(str, 'B') == &str[4]); } +TEST(xstrndup8) { + char *s = NULL; + + assert_se(xstrndup8(NULL, 0) == NULL); + assert_se(xstrndup8(NULL, 10) == NULL); + + assert_se(s = xstrndup8("", 10)); + assert_se(streq8(s, "")); + free(s); + + assert_se(s = xstrndup8("abc", 0)); + assert_se(streq8(s, "")); + free(s); + + assert_se(s = xstrndup8("ABC", 3)); + assert_se(streq8(s, "ABC")); + free(s); + + assert_se(s = xstrndup8("123abcDEF", 5)); + assert_se(streq8(s, "123ab")); + free(s); +} + +TEST(xstrdup8) { + char *s = NULL; + + assert_se(xstrdup8(NULL) == NULL); + + assert_se(s = xstrdup8("")); + assert_se(streq8(s, "")); + free(s); + + assert_se(s = xstrdup8("1")); + assert_se(streq8(s, "1")); + free(s); + + assert_se(s = xstrdup8("123abcDEF")); + assert_se(streq8(s, "123abcDEF")); + free(s); +} + +TEST(xstrndup16) { + char16_t *s = NULL; + + assert_se(xstrndup16(NULL, 0) == NULL); + assert_se(xstrndup16(NULL, 10) == NULL); + + assert_se(s = xstrndup16(u"", 10)); + assert_se(streq16(s, u"")); + free(s); + + assert_se(s = xstrndup16(u"abc", 0)); + assert_se(streq16(s, u"")); + free(s); + + assert_se(s = xstrndup16(u"ABC", 3)); + assert_se(streq16(s, u"ABC")); + free(s); + + assert_se(s = xstrndup16(u"123abcDEF", 5)); + assert_se(streq16(s, u"123ab")); + free(s); +} + +TEST(xstrdup16) { + char16_t *s = NULL; + + assert_se(xstrdup16(NULL) == NULL); + + assert_se(s = xstrdup16(u"")); + assert_se(streq16(s, u"")); + free(s); + + assert_se(s = xstrdup16(u"1")); + assert_se(streq16(s, u"1")); + free(s); + + assert_se(s = xstrdup16(u"123abcDEF")); + assert_se(streq16(s, u"123abcDEF")); + free(s); +} + TEST(efi_memcmp) { assert_se(efi_memcmp(NULL, NULL, 0) == 0); assert_se(efi_memcmp(NULL, NULL, 1) == 0); diff --git a/src/boot/efi/util.c b/src/boot/efi/util.c index 83e03fa835d..06859d2f3a3 100644 --- a/src/boot/efi/util.c +++ b/src/boot/efi/util.c @@ -552,26 +552,6 @@ EFI_STATUS readdir_harder( return EFI_SUCCESS; } -CHAR8 *xstrndup8(const CHAR8 *p, UINTN sz) { - CHAR8 *n; - - /* Following efilib's naming scheme this function would be called strndupa(), but we already have a - * function named like this in userspace, and it does something different there, hence to minimize - * confusion, let's pick a different name here */ - - assert(p || sz == 0); - - sz = strnlen8((const char *) p, sz); - - n = xallocate_pool(sz + 1); - - if (sz > 0) - memcpy(n, p, sz); - n[sz] = 0; - - return n; -} - BOOLEAN is_ascii(const CHAR16 *f) { if (!f) return FALSE; diff --git a/src/boot/efi/util.h b/src/boot/efi/util.h index 2a50336f324..fcfadf3a6eb 100644 --- a/src/boot/efi/util.h +++ b/src/boot/efi/util.h @@ -119,8 +119,6 @@ EFI_STATUS get_file_info_harder(EFI_FILE *handle, EFI_FILE_INFO **ret, UINTN *re EFI_STATUS readdir_harder(EFI_FILE *handle, EFI_FILE_INFO **buffer, UINTN *buffer_size); -CHAR8 *xstrndup8(const CHAR8 *p, UINTN sz); - BOOLEAN is_ascii(const CHAR16 *f); CHAR16 **strv_free(CHAR16 **l);