From b92057584f09d442f27b9177b12fe6fdf36ddbaf Mon Sep 17 00:00:00 2001 From: Frank Mehnert Date: Tue, 7 Jan 2025 13:09:50 +0100 Subject: fix possible overflow in pointer arithmetics strnlen() It is undefined behavior to compare two pointers belonging to different objects. This includes the case where the addition overflows. Clang-20 seems to follow this rule more eagerly and optimizes away the old test. Fix the test by performing the addition on uintptr_t values rather than on on char pointers. See also https://github.com/llvm/llvm-project/issues/121909. Signed-off-by: Marcus Haehnel --- libc/string/generic/strnlen.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libc/string/generic/strnlen.c b/libc/string/generic/strnlen.c index 4d4cde84f..82d4122ec 100644 --- a/libc/string/generic/strnlen.c +++ b/libc/string/generic/strnlen.c @@ -29,15 +29,17 @@ '\0' terminator is found in that many characters, return MAXLEN. */ size_t strnlen (const char *str, size_t maxlen) { - const char *char_ptr, *end_ptr = str + maxlen; + const char *char_ptr, *end_ptr; const unsigned long int *longword_ptr; unsigned long int longword, himagic, lomagic; if (maxlen == 0) return 0; - if (__builtin_expect (end_ptr < str, 0)) + if (__builtin_expect ((uintptr_t)str + maxlen < (uintptr_t)str, 0)) end_ptr = (const char *) ~0UL; + else + end_ptr = str + maxlen; /* Handle the first few characters by reading one character at a time. Do this until CHAR_PTR is aligned on a longword boundary. */ -- cgit v1.2.3