From f9ab107d32f9a92841430866096a63746bb96fe2 Mon Sep 17 00:00:00 2001
From: Julius Werner <jwerner@chromium.org>
Date: Thu, 15 Aug 2024 13:43:12 -0700
Subject: commonlib/bsd: Optimize strnlen()

This patch changes the strnlen() implementation to fix a small issue
where we would dereference once more byte than intended when not finding
a NUL-byte within the specified amount of characters. It also changes
the implementation to rely on a pre-calculated end pointer rather than a
running counter, since this seems to lead to slightly better assembly
(one less instruction in the inner loop) on most architectures.

Change-Id: Ic36768fd3a26e2b64143904e78cd0b52ba66898d
Signed-off-by: Julius Werner <jwerner@chromium.org>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/83933
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Yu-Ping Wu <yupingso@google.com>
---
 src/commonlib/bsd/string.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

(limited to 'src/commonlib/bsd')

diff --git a/src/commonlib/bsd/string.c b/src/commonlib/bsd/string.c
index 56670e8862..6482279713 100644
--- a/src/commonlib/bsd/string.c
+++ b/src/commonlib/bsd/string.c
@@ -15,10 +15,19 @@ size_t strlen(const char *str)
 
 size_t strnlen(const char *str, size_t maxlen)
 {
-	size_t len = 0;
-	while (*str++ && len < maxlen)
-		len++;
-	return len;
+	const char *ptr = str;
+	const char *end = str + maxlen;
+
+	if (!maxlen)
+		return 0;
+
+	while (*ptr++) {
+		/* Make sure this checks for ==, not >=, because the calculation
+		   for `end` may overflow in some edge cases. */
+		if (ptr == end)
+			return maxlen;
+	}
+	return ptr - str - 1;
 }
 
 char *strcat(char *dst, const char *src)
-- 
cgit v1.2.3