summaryrefslogtreecommitdiff
path: root/util/libreboot-utils/lib/string.c
diff options
context:
space:
mode:
authorLeah Rowe <leah@libreboot.org>2026-03-29 22:15:27 +0100
committerLeah Rowe <leah@libreboot.org>2026-03-29 23:55:38 +0100
commit7fb0b2f69293f0fb0e83e9b125fbd658503147f0 (patch)
treef7c119ee9dc7ffbb6ad62bc360ddc52212413167 /util/libreboot-utils/lib/string.c
parent01aa95ec15ed5a6e519f1d3887e105a40e17b84c (diff)
libreboot-utils: safe memcmpHEADmaster
Signed-off-by: Leah Rowe <leah@libreboot.org>
Diffstat (limited to 'util/libreboot-utils/lib/string.c')
-rw-r--r--util/libreboot-utils/lib/string.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/util/libreboot-utils/lib/string.c b/util/libreboot-utils/lib/string.c
index 39b31cb0..49c23663 100644
--- a/util/libreboot-utils/lib/string.c
+++ b/util/libreboot-utils/lib/string.c
@@ -292,6 +292,39 @@ err:
return -1;
}
+/* because no libc reimagination is complete
+ * without a reimplementation of memcmp. and
+ * no safe one is complete without null checks.
+ */
+int
+vcmp(const void *s1, const void *s2, size_t n)
+{
+ size_t i = 0;
+ size_t a;
+ size_t b;
+
+ if (if_err(s1 == NULL || s2 == NULL, EFAULT))
+ err_exit(EFAULT, "vcmp: null input");
+
+ const unsigned char *x = s1;
+ const unsigned char *y = s2;
+
+ for ( ; i + sizeof(size_t) <= n; i += sizeof(size_t)) {
+
+ memcpy(&a, x + i, sizeof(size_t));
+ memcpy(&b, y + i, sizeof(size_t));
+
+ if (a != b)
+ break;
+ }
+
+ for ( ; i < n; i++)
+ if (x[i] != y[i])
+ return (int)x[i] - (int)y[i];
+
+ return 0;
+}
+
/* on functions that return with errno,
* i sometimes have a default fallback,
* which is set if errno wasn't changed,