Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 12 Aug 2025 09:59:57 GMT
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: d180086e6eae - main - [libm] Fix undefined behavior of a left shifted of a signed integer
Message-ID:  <202508120959.57C9xv61050397@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=d180086e6eae2e152e803ed6cf13775a7c006dc7

commit d180086e6eae2e152e803ed6cf13775a7c006dc7
Author:     Steve Kargl <kargl@FreeBSD.org>
AuthorDate: 2025-08-12 04:26:29 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2025-08-12 05:31:03 +0000

    [libm] Fix undefined behavior of a left shifted of a signed integer
    
    The patch fixes a few instances of left shifts on
    signed integer entities.  A 'static inline' helper function
    'subnormal_ilogb()' has been added to math_private.h.  This
    function is then used e_fmod.c, s_ilogb(), and s_remquo.c.
    
    The change in s_remquo.c has only been compile tested.
    
    The change to e_fmod.c has been test on over 3 billion pairs
    of subnormal numbers where testing included x > y and x < y
    pairs.  The test compared the output from fmod() with the
    output from mpfr_fmod() from MPFR.  There were no difference.
    
    The change to s_ilogb() has had limited testing where its
    output was compared against frexp().  In this testing, no
    differences in output were detected.
    
    PR:     288778
    MFC after:      1 week
---
 lib/msun/src/e_fmod.c       | 30 ++++++++++++------------------
 lib/msun/src/math_private.h | 21 +++++++++++++++++++++
 lib/msun/src/s_ilogb.c      | 13 +++++--------
 lib/msun/src/s_remquo.c     | 30 ++++++++++++------------------
 4 files changed, 50 insertions(+), 44 deletions(-)

diff --git a/lib/msun/src/e_fmod.c b/lib/msun/src/e_fmod.c
index 77afd116c658..ced9cce33aa0 100644
--- a/lib/msun/src/e_fmod.c
+++ b/lib/msun/src/e_fmod.c
@@ -26,14 +26,14 @@ static const double one = 1.0, Zero[] = {0.0, -0.0,};
 double
 fmod(double x, double y)
 {
-	int32_t n,hx,hy,hz,ix,iy,sx,i;
-	u_int32_t lx,ly,lz;
+	int32_t hx, hy, hz, ix, iy, n, sx;
+	u_int32_t lx, ly, lz;
 
 	EXTRACT_WORDS(hx,lx,x);
 	EXTRACT_WORDS(hy,ly,y);
 	sx = hx&0x80000000;		/* sign of x */
-	hx ^=sx;		/* |x| */
-	hy &= 0x7fffffff;	/* |y| */
+	hx ^= sx;			/* |x| */
+	hy &= 0x7fffffff;		/* |y| */
 
     /* purge off exception values */
 	if((hy|ly)==0||(hx>=0x7ff00000)||	/* y=0,or x not finite */
@@ -46,22 +46,16 @@ fmod(double x, double y)
 	}
 
     /* determine ix = ilogb(x) */
-	if(hx<0x00100000) {	/* subnormal x */
-	    if(hx==0) {
-		for (ix = -1043, i=lx; i>0; i<<=1) ix -=1;
-	    } else {
-		for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1;
-	    }
-	} else ix = (hx>>20)-1023;
+	if(hx<0x00100000)
+	    ix = subnormal_ilogb(hx, lx);
+	else
+	    ix = (hx>>20)-1023;
 
     /* determine iy = ilogb(y) */
-	if(hy<0x00100000) {	/* subnormal y */
-	    if(hy==0) {
-		for (iy = -1043, i=ly; i>0; i<<=1) iy -=1;
-	    } else {
-		for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1;
-	    }
-	} else iy = (hy>>20)-1023;
+	if(hy<0x00100000)
+	    iy = subnormal_ilogb(hy, ly);
+	else
+	    iy = (hy>>20)-1023;
 
     /* set up {hx,lx}, {hy,ly} and align y to x */
 	if(ix >= -1022) 
diff --git a/lib/msun/src/math_private.h b/lib/msun/src/math_private.h
index 1595f902846c..0711f2f33c41 100644
--- a/lib/msun/src/math_private.h
+++ b/lib/msun/src/math_private.h
@@ -739,6 +739,27 @@ irintl(long double x)
 	(ar) = (x) - (ai);				\
 } while (0)
 
+/*
+ * For a double entity split into high and low parts, compute ilogb.
+ */
+static inline int32_t
+subnormal_ilogb(int32_t hi, int32_t lo)
+{
+	int32_t j;
+	uint32_t i;
+
+	j = -1022;
+	if (hi == 0) {
+	    j -= 21;
+	    i = (uint32_t)lo;
+	} else
+	    i = (uint32_t)hi << 11;
+
+	for (; i < 0x7fffffff; i <<= 1) j -= 1;
+
+	return (j);
+}
+
 #ifdef DEBUG
 #if defined(__amd64__) || defined(__i386__)
 #define	breakpoint()	asm("int $3")
diff --git a/lib/msun/src/s_ilogb.c b/lib/msun/src/s_ilogb.c
index 27e0bbb8735b..aa707d51d7b7 100644
--- a/lib/msun/src/s_ilogb.c
+++ b/lib/msun/src/s_ilogb.c
@@ -21,21 +21,18 @@
 #include "math.h"
 #include "math_private.h"
 
-	int ilogb(double x)
+int
+ilogb(double x)
 {
-	int32_t hx,lx,ix;
+	int32_t hx, ix, lx;
 
 	EXTRACT_WORDS(hx,lx,x);
 	hx &= 0x7fffffff;
 	if(hx<0x00100000) {
 	    if((hx|lx)==0)
 		return FP_ILOGB0;
-	    else			/* subnormal x */
-		if(hx==0) {
-		    for (ix = -1043; lx>0; lx<<=1) ix -=1;
-		} else {
-		    for (ix = -1022,hx<<=11; hx>0; hx<<=1) ix -=1;
-		}
+	    else
+		ix = subnormal_ilogb(hx, lx);
 	    return ix;
 	}
 	else if (hx<0x7ff00000) return (hx>>20)-1023;
diff --git a/lib/msun/src/s_remquo.c b/lib/msun/src/s_remquo.c
index 206d2903cd86..b26b5619f3ad 100644
--- a/lib/msun/src/s_remquo.c
+++ b/lib/msun/src/s_remquo.c
@@ -4,7 +4,7 @@
  *
  * Developed at SunSoft, a Sun Microsystems, Inc. business.
  * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice 
+ * software is freely granted, provided that this notice
  * is preserved.
  * ====================================================
  */
@@ -27,7 +27,7 @@ static const double Zero[] = {0.0, -0.0,};
 double
 remquo(double x, double y, int *quo)
 {
-	int32_t n,hx,hy,hz,ix,iy,sx,i;
+	int32_t hx,hy,hz,ix,iy,n,sx;
 	u_int32_t lx,ly,lz,q,sxy;
 
 	EXTRACT_WORDS(hx,lx,x);
@@ -53,25 +53,19 @@ remquo(double x, double y, int *quo)
 	}
 
     /* determine ix = ilogb(x) */
-	if(hx<0x00100000) {	/* subnormal x */
-	    if(hx==0) {
-		for (ix = -1043, i=lx; i>0; i<<=1) ix -=1;
-	    } else {
-		for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1;
-	    }
-	} else ix = (hx>>20)-1023;
+	if(hx<0x00100000)
+	    ix = subnormal_ilogb(hx, lx);
+	else
+	    ix = (hx>>20)-1023;
 
     /* determine iy = ilogb(y) */
-	if(hy<0x00100000) {	/* subnormal y */
-	    if(hy==0) {
-		for (iy = -1043, i=ly; i>0; i<<=1) iy -=1;
-	    } else {
-		for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1;
-	    }
-	} else iy = (hy>>20)-1023;
+	if(hy<0x00100000)
+	    iy = subnormal_ilogb(hy, ly);
+	else
+	    iy = (hy>>20)-1023;
 
     /* set up {hx,lx}, {hy,ly} and align y to x */
-	if(ix >= -1022) 
+	if(ix >= -1022)
 	    hx = 0x00100000|(0x000fffff&hx);
 	else {		/* subnormal x, shift x to normal */
 	    n = -1022-ix;
@@ -83,7 +77,7 @@ remquo(double x, double y, int *quo)
 		lx = 0;
 	    }
 	}
-	if(iy >= -1022) 
+	if(iy >= -1022)
 	    hy = 0x00100000|(0x000fffff&hy);
 	else {		/* subnormal y, shift y to normal */
 	    n = -1022-iy;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202508120959.57C9xv61050397>