]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
boot: Add strlen8/16
authorJan Janssen <medhefgo@web.de>
Mon, 23 May 2022 09:23:40 +0000 (11:23 +0200)
committerJan Janssen <medhefgo@web.de>
Tue, 31 May 2022 12:18:43 +0000 (14:18 +0200)
src/boot/efi/efi-string.c [new file with mode: 0644]
src/boot/efi/efi-string.h [new file with mode: 0644]
src/boot/efi/meson.build
src/boot/efi/test-efi-string.c [new file with mode: 0644]

diff --git a/src/boot/efi/efi-string.c b/src/boot/efi/efi-string.c
new file mode 100644 (file)
index 0000000..2c15489
--- /dev/null
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "efi-string.h"
+
+/* 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
+ * easier to tell in code which kind of string they work on, we use 8/16 suffixes. This also makes is easier
+ * to unit test them. */
+
+#define DEFINE_STRNLEN(type, name)             \
+        size_t name(const type *s, size_t n) { \
+                if (!s)                        \
+                        return 0;              \
+                                               \
+                size_t len = 0;                \
+                while (len < n && *s) {        \
+                        s++;                   \
+                        len++;                 \
+                }                              \
+                                               \
+                return len;                    \
+        }
+
+DEFINE_STRNLEN(char, strnlen8);
+DEFINE_STRNLEN(char16_t, strnlen16);
+
+size_t strlen8(const char *s) {
+        return strnlen8(s, SIZE_MAX);
+}
+
+size_t strlen16(const char16_t *s) {
+        return strnlen16(s, SIZE_MAX);
+}
diff --git a/src/boot/efi/efi-string.h b/src/boot/efi/efi-string.h
new file mode 100644 (file)
index 0000000..ba98ac3
--- /dev/null
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include <stddef.h>
+#include <uchar.h>
+
+size_t strnlen8(const char *s, size_t n);
+size_t strnlen16(const char16_t *s, size_t n);
+
+size_t strlen8(const char *s);
+size_t strlen16(const char16_t *s);
index 8f1645202b4a3cd3eaaa4c1f362bb550e5b343a2..f6c19fea33749995654d0066a270ec118ed016cb 100644 (file)
@@ -331,6 +331,7 @@ efi_headers = files(
         'devicetree.h',
         'disk.h',
         'drivers.h',
+        'efi-string.h',
         'graphics.h',
         'initrd.h',
         'linux.h',
@@ -350,6 +351,7 @@ common_sources = files(
         'assert.c',
         'devicetree.c',
         'disk.c',
+        'efi-string.c',
         'graphics.c',
         'initrd.c',
         'measure.c',
@@ -380,6 +382,10 @@ else
         stub_sources += files('linux.c')
 endif
 
+tests += [
+        [files('test-efi-string.c', 'efi-string.c')],
+]
+
 # BCD parser only makes sense on arches that Windows supports.
 if efi_arch[1] in ['ia32', 'x86_64', 'arm', 'aarch64']
         systemd_boot_sources += files('bcd.c')
diff --git a/src/boot/efi/test-efi-string.c b/src/boot/efi/test-efi-string.c
new file mode 100644 (file)
index 0000000..aab2ffb
--- /dev/null
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "efi-string.h"
+#include "tests.h"
+
+TEST(strlen8) {
+        assert_se(strlen8(NULL) == 0);
+        assert_se(strlen8("") == 0);
+        assert_se(strlen8("1") == 1);
+        assert_se(strlen8("11") == 2);
+        assert_se(strlen8("123456789") == 9);
+        assert_se(strlen8("12\0004") == 2);
+}
+
+TEST(strlen16) {
+        assert_se(strlen16(NULL) == 0);
+        assert_se(strlen16(u"") == 0);
+        assert_se(strlen16(u"1") == 1);
+        assert_se(strlen16(u"11") == 2);
+        assert_se(strlen16(u"123456789") == 9);
+        assert_se(strlen16(u"12\0004") == 2);
+}
+
+TEST(strnlen8) {
+        assert_se(strnlen8(NULL, 0) == 0);
+        assert_se(strnlen8(NULL, 10) == 0);
+        assert_se(strnlen8("", 10) == 0);
+        assert_se(strnlen8("1", 10) == 1);
+        assert_se(strnlen8("11", 1) == 1);
+        assert_se(strnlen8("123456789", 7) == 7);
+        assert_se(strnlen8("12\0004", 5) == 2);
+}
+
+TEST(strnlen16) {
+        assert_se(strnlen16(NULL, 0) == 0);
+        assert_se(strnlen16(NULL, 10) == 0);
+        assert_se(strnlen16(u"", 10) == 0);
+        assert_se(strnlen16(u"1", 10) == 1);
+        assert_se(strnlen16(u"11", 1) == 1);
+        assert_se(strnlen16(u"123456789", 7) == 7);
+        assert_se(strnlen16(u"12\0004", 5) == 2);
+}
+
+DEFINE_TEST_MAIN(LOG_INFO);