]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
efi-string: Add efi_memchr()
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Tue, 31 Jan 2023 14:39:40 +0000 (15:39 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 23 Feb 2023 08:49:56 +0000 (09:49 +0100)
src/boot/efi/efi-string.c
src/boot/efi/efi-string.h
src/boot/efi/test-efi-string.c

index 911579ed5b603dd98644d4984934bca715a8aa73..a94e2e4c17bb0238b8f744be238f33c42bdd815c 100644 (file)
@@ -878,16 +878,30 @@ char16_t *xvasprintf_status(EFI_STATUS status, const char *format, va_list ap) {
 
 #if SD_BOOT
 /* To provide the actual implementation for these we need to remove the redirection to the builtins. */
+#  undef memchr
 #  undef memcmp
 #  undef memcpy
 #  undef memset
 #else
 /* And for userspace unit testing we need to give them an efi_ prefix. */
+#  define memchr efi_memchr
 #  define memcmp efi_memcmp
 #  define memcpy efi_memcpy
 #  define memset efi_memset
 #endif
 
+_used_ void *memchr(const void *p, int c, size_t n) {
+        if (!p || n == 0)
+                return NULL;
+
+        const uint8_t *q = p;
+        for (size_t i = 0; i < n; i++)
+                if (q[i] == (unsigned char) c)
+                        return (void *) (q + i);
+
+        return NULL;
+}
+
 _used_ int memcmp(const void *p1, const void *p2, size_t n) {
         const uint8_t *up1 = p1, *up2 = p2;
         int r;
index 0927bbf82df4876a1fbe1840100c986e7dcc1df7..410bfd8ef5e5dff11379ee62e72534d2b9f0bf2b 100644 (file)
@@ -153,6 +153,7 @@ _gnu_printf_(2, 0) _warn_unused_result_ char16_t *xvasprintf_status(EFI_STATUS s
  * compiling with -ffreestanding. By referring to builtins, the compiler can check arguments and do
  * optimizations again. Note that we still need to provide implementations as the compiler is free to not
  * inline its own implementation and instead issue a library call. */
+#  define memchr __builtin_memchr
 #  define memcmp __builtin_memcmp
 #  define memcpy __builtin_memcpy
 #  define memset __builtin_memset
@@ -166,6 +167,7 @@ static inline void *mempcpy(void * restrict dest, const void * restrict src, siz
 
 #else
 /* For unit testing. */
+void *efi_memchr(const void *p, int c, size_t n);
 int efi_memcmp(const void *p1, const void *p2, size_t n);
 void *efi_memcpy(void * restrict dest, const void * restrict src, size_t n);
 void *efi_memset(void *p, int c, size_t n);
index be7f8f9b1c8e2eef24eca6851956f648dd7a9a44..d214b1536e3160863b4cd7a2bd6f2f8b22c3aefe 100644 (file)
@@ -626,6 +626,19 @@ TEST(xvasprintf_status) {
         s = mfree(s);
 }
 
+TEST(efi_memchr) {
+        assert_se(streq8(efi_memchr("abcde", 'c', 5), "cde"));
+        assert_se(streq8(efi_memchr("abcde", 'c', 3), "cde"));
+        assert_se(streq8(efi_memchr("abcde", 'c', 2), NULL));
+        assert_se(streq8(efi_memchr("abcde", 'c', 7), "cde"));
+        assert_se(streq8(efi_memchr("abcde", 'q', 5), NULL));
+        assert_se(streq8(efi_memchr("abcde", 'q', 0), NULL));
+        /* Test that the character is interpreted as unsigned char. */
+        assert_se(streq8(efi_memchr("abcde", 'a', 6), efi_memchr("abcde", 'a' + 0x100, 6)));
+        assert_se(streq8(efi_memchr("abcde", 0, 6), ""));
+        assert_se(efi_memchr(NULL, 0, 0) == NULL);
+}
+
 TEST(efi_memcmp) {
         assert_se(efi_memcmp(NULL, NULL, 0) == 0);
         assert_se(efi_memcmp(NULL, NULL, 1) == 0);