[glibc/azanella/ubsan-undef] string: Fix UB on index_first/index_last

Adhemerval Zanella azanella@sourceware.org
Wed May 7 14:15:37 GMT 2025


https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=a67a8eda72ad95b265db9ea1d3b914c9a1d9a5c9

commit a67a8eda72ad95b265db9ea1d3b914c9a1d9a5c9
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date:   Tue Apr 22 14:34:27 2025 -0300

    string: Fix UB on index_first/index_last
    
    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.

Diff:
---
 sysdeps/generic/string-fzi.h | 27 +++++----------------------
 1 file changed, 5 insertions(+), 22 deletions(-)

diff --git a/sysdeps/generic/string-fzi.h b/sysdeps/generic/string-fzi.h
index 3c1028d1ec..f90f662ac2 100644
--- a/sysdeps/generic/string-fzi.h
+++ b/sysdeps/generic/string-fzi.h
@@ -19,28 +19,11 @@
 #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);
 }


More information about the Glibc-cvs mailing list