summaryrefslogtreecommitdiff
path: root/libc/string/generic
diff options
context:
space:
mode:
authorFrank Mehnert <frank.mehnert@kernkonzept.com>2025-01-07 13:09:50 +0100
committerWaldemar Brodkorb <wbx@openadk.org>2025-01-07 13:28:17 +0100
commitb92057584f09d442f27b9177b12fe6fdf36ddbaf (patch)
tree10f251b3ce388177ba027e5121f42003ab98aad5 /libc/string/generic
parent1de51fb74b68a94207384021a878c1a3035d2aff (diff)
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 <marcus.haehnel@kernkonzept.com>
Diffstat (limited to 'libc/string/generic')
-rw-r--r--libc/string/generic/strnlen.c6
1 files 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. */