Просмотр исходного кода

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>
Frank Mehnert 9 месяцев назад
Родитель
Сommit
b92057584f
1 измененных файлов с 4 добавлено и 2 удалено
  1. 4 2
      libc/string/generic/strnlen.c

+ 4 - 2
libc/string/generic/strnlen.c

@@ -29,15 +29,17 @@
    '\0' terminator is found in that many characters, return MAXLEN.  */
    '\0' terminator is found in that many characters, return MAXLEN.  */
 size_t strnlen (const char *str, size_t 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;
   const unsigned long int *longword_ptr;
   unsigned long int longword, himagic, lomagic;
   unsigned long int longword, himagic, lomagic;
 
 
   if (maxlen == 0)
   if (maxlen == 0)
     return 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;
     end_ptr = (const char *) ~0UL;
+  else
+    end_ptr = str + maxlen;
 
 
   /* Handle the first few characters by reading one character at a time.
   /* Handle the first few characters by reading one character at a time.
      Do this until CHAR_PTR is aligned on a longword boundary.  */
      Do this until CHAR_PTR is aligned on a longword boundary.  */