]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
string: Remove UB on ffs/ffsll
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>
Fri, 25 Apr 2025 17:28:22 +0000 (14:28 -0300)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Thu, 8 May 2025 12:25:49 +0000 (09:25 -0300)
Building with ubsan on 32 bit architecture, tst-ffs shows:

ffsll(0x4000000000000000) as expected 63
UBSAN: Undefined behaviour in ffsll.c:37:34 negation of 9223372036854775808 cannot be represented in type 'long long int'

Since the idea is to isolate the least significant bit, use unsigned
types.

string/ffs.c
string/ffsll.c

index a2aa5b1242d3cf82b56a635dca5d29030ff714d2..eda9f491977149989e611ec6f4d5162a6b989a1b 100644 (file)
@@ -40,7 +40,9 @@ __ffs (int i)
       8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
     };
   unsigned int a;
-  unsigned int x = i & -i;
+  /* Isolate the least significant one.  */
+  unsigned int u_i = i;
+  unsigned int x = u_i & -u_i;
 
   a = x <= 0xffff ? (x <= 0xff ? 0 : 8) : (x <= 0xffffff ?  16 : 24);
 
index 1b01d8fb122ea39cd0cf7aaa974b18a8aeea0c64..ed2c877ad03c3b0bafdb70440be514fbbd24d38c 100644 (file)
@@ -29,7 +29,9 @@ __ffsll (long long int i)
 #if USE_FFSLL_BUILTIN
   return __builtin_ffsll (i);
 #else
-  unsigned long long int x = i & -i;
+  /* Isolate the least significant one.  */
+  unsigned long long int i_u = i;
+  unsigned long long int x = i_u & -i_u;
 
   if (x <= 0xffffffff)
     return ffs (i);