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;
#include "efi-string.h"
+#ifdef SD_BOOT
+# include "util.h"
+# define xmalloc(n) xallocate_pool(n)
+#else
+# include <stdlib.h>
+# 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
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);
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
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);
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;
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);