]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
string: Fix UB on index_first/index_last
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>
Tue, 22 Apr 2025 17:34:27 +0000 (14:34 -0300)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Wed, 7 May 2025 17:21:21 +0000 (14:21 -0300)
Building with ubsan the test-strcnmp triggers:

UBSAN: Undefined behaviour in ../sysdeps/generic/string-fzi.h:39:12 passing zero to __builtin_ctz()

Use stdbit.h functions instead of ctl/clz.

sysdeps/generic/string-fzi.h

index 3c1028d1ec0a7b56a61f1e72173a709e29331ada..f90f662ac2cec174326f1516bdd546059ecc1d7f 100644 (file)
 #ifndef _STRING_FZI_H
 #define _STRING_FZI_H 1
 
+#include <stdbit.h>
 #include <limits.h>
 #include <endian.h>
 #include <string-fza.h>
 
-static __always_inline int
-clz (find_t c)
-{
-  if (sizeof (find_t) == sizeof (unsigned long))
-    return __builtin_clzl (c);
-  else
-    return __builtin_clzll (c);
-}
-
-static __always_inline int
-ctz (find_t c)
-{
-  if (sizeof (find_t) == sizeof (unsigned long))
-    return __builtin_ctzl (c);
-  else
-    return __builtin_ctzll (c);
-}
-
 /* A subroutine for the index_zero functions.  Given a test word C, return
    the (memory order) index of the first byte (in memory order) that is
    non-zero.  */
@@ -49,9 +32,9 @@ index_first (find_t c)
 {
   int r;
   if (__BYTE_ORDER == __LITTLE_ENDIAN)
-    r = ctz (c);
+    r = stdc_trailing_zeros (c);
   else
-    r = clz (c);
+    r = stdc_leading_zeros (c);
   return r / CHAR_BIT;
 }
 
@@ -62,9 +45,9 @@ index_last (find_t c)
 {
   int r;
   if (__BYTE_ORDER == __LITTLE_ENDIAN)
-    r = clz (c);
+    r = stdc_leading_zeros (c);
   else
-    r = ctz (c);
+    r = stdc_trailing_zeros (c);
   return sizeof (find_t) - 1 - (r / CHAR_BIT);
 }