From: Jan Janssen Date: Mon, 23 May 2022 09:23:40 +0000 (+0200) Subject: boot: Add strlen8/16 X-Git-Tag: v252-rc1~892^2~16 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9080ffd4cdebedf55974e8f8d8b05ff4385bd1e1;p=thirdparty%2Fsystemd.git boot: Add strlen8/16 --- diff --git a/src/boot/efi/efi-string.c b/src/boot/efi/efi-string.c new file mode 100644 index 00000000000..2c1548936d4 --- /dev/null +++ b/src/boot/efi/efi-string.c @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include +#include + +#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 index 00000000000..ba98ac37543 --- /dev/null +++ b/src/boot/efi/efi-string.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include +#include + +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); diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build index 8f1645202b4..f6c19fea337 100644 --- a/src/boot/efi/meson.build +++ b/src/boot/efi/meson.build @@ -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 index 00000000000..aab2ffb4dbc --- /dev/null +++ b/src/boot/efi/test-efi-string.c @@ -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);