]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
stdlib: Fix UB on strtod
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>
Tue, 22 Apr 2025 17:20:12 +0000 (14:20 -0300)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Wed, 7 May 2025 17:21:21 +0000 (14:21 -0300)
With glibc built with ubsan it triggers:

UBSAN: Undefined behaviour in strtod_l.c:1580:8 shift exponent 41 is too large for 32-bit type 'int'

Use the correct constant literal definition based on mp_limb_t size.

stdlib/strtod_l.c

index f9572b9ebfdad5a2fa1927551201f35ccf9422d9..06a93e2afeff7e94fd53861c7be7c2a04f8f29fc 100644 (file)
@@ -150,9 +150,11 @@ extern FLOAT MPN2FLOAT (mp_srcptr mpn, int exponent, int negative);
 #if    BITS_PER_MP_LIMB == 32
 # define MAX_DIG_PER_LIMB      9
 # define MAX_FAC_PER_LIMB      1000000000UL
+# define SHIFT_CTE(N)          N # U
 #elif  BITS_PER_MP_LIMB == 64
 # define MAX_DIG_PER_LIMB      19
 # define MAX_FAC_PER_LIMB      10000000000000000000ULL
+# define SHIFT_CTE(N)          N ## UL
 #else
 # error "mp_limb_t size " BITS_PER_MP_LIMB "not accounted for"
 #endif
@@ -1572,12 +1574,13 @@ ____STRTOF_INTERNAL (const STRING_TYPE *nptr, STRING_TYPE **endptr, int group,
                    {
                      if (bits + BITS_PER_MP_LIMB <= MANT_DIG)
                        __mpn_lshift_1 (retval, RETURN_LIMB_SIZE,
-                                       BITS_PER_MP_LIMB, 0);
+                                       BITS_PER_MP_LIMB, SHIFT_CTE (0));
                      else
                        {
                          used = MANT_DIG - bits;
                          if (used > 0)
-                           __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, 0);
+                           __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used,
+                                           SHIFT_CTE (0));
                        }
                      bits += BITS_PER_MP_LIMB;
                    }