]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/commit
MFC r352710:
authordim <dim@ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f>
Sat, 28 Sep 2019 08:57:29 +0000 (08:57 +0000)
committerdim <dim@ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f>
Sat, 28 Sep 2019 08:57:29 +0000 (08:57 +0000)
commitb708735349f05b16213b4854c8ea7dc19783ad85
treef265f81653aeadc6d85db72226f712cb2d635284
parentb88eafa2ff7f913e2090a156d696d8d4604c364d
MFC r352710:

Do not left-shift a negative number (inducing undefined behavior in
C/C++) in exp(3), expf(3), expm1(3) and expm1f(3) during intermediate
computations that compute the IEEE-754 bit pattern for |2**k| for
integer |k|.

The implementations of exp(3), expf(3), expm1(3) and expm1f(3) need to
compute IEEE-754 bit patterns for 2**k in certain places.  (k is an
integer and 2**k is exactly representable in IEEE-754.)

Currently they do things like 0x3FF0'0000+(k<<20), which is to say they
take the bit pattern representing 1 and then add directly to the
exponent field to get the desired power of two.  This is fine when k is
non-negative.

But when k<0 (and certain classes of input trigger this), this
left-shifts a negative number -- an operation with undefined behavior in
C and C++.

The desired semantics can be achieved by instead adding the
possibly-negative k to the IEEE-754 exponent bias to get the desired
exponent field, _then_ shifting that into its proper overall position.

(Note that in case of s_expm1.c and s_expm1f.c, there are SET_HIGH_WORD
and SET_FLOAT_WORD uses further down in each of these files that perform
shift operations involving k, but by these points k's range has been
restricted to 2 < k <= 56, and the shift operations under those
circumstances can't do anything that would be UB.)

Submitted by: Jeff Walden, https://github.com/jswalden
Obtained from: https://github.com/freebsd/freebsd/pull/411
Obtained from: https://github.com/freebsd/freebsd/pull/412

git-svn-id: svn://svn.freebsd.org/base/stable/8@352835 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f
lib/msun/src/e_exp.c
lib/msun/src/e_expf.c
lib/msun/src/s_expm1.c
lib/msun/src/s_expm1f.c