Avoid undefined behaviour in ibm128 implementation of llroundl (BZ #29488)

Detecting an overflow edge case depended on signed overflow of a long
long. Replace the additions and the overflow checks by
__builtin_add_overflow().

Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
This commit is contained in:
Aurelien Jarno 2022-10-10 00:39:33 +02:00
parent be930668ec
commit 2b5478569e

View File

@ -66,38 +66,35 @@ __llroundl (long double x)
/* Peg at max/min values, assuming that the above conversions do so. /* Peg at max/min values, assuming that the above conversions do so.
Strictly speaking, we can return anything for values that overflow, Strictly speaking, we can return anything for values that overflow,
but this is more useful. */ but this is more useful. */
res = hi + lo; if (__glibc_unlikely (__builtin_add_overflow (hi, lo, &res)))
/* This is just sign(hi) == sign(lo) && sign(res) != sign(hi). */
if (__glibc_unlikely (((~(hi ^ lo) & (res ^ hi)) < 0)))
goto overflow; goto overflow;
xh -= lo; xh -= lo;
ldbl_canonicalize (&xh, &xl); ldbl_canonicalize (&xh, &xl);
hi = res;
if (xh > 0.5) if (xh > 0.5)
{ {
res += 1; if (__glibc_unlikely (__builtin_add_overflow (res, 1, &res)))
goto overflow;
} }
else if (xh == 0.5) else if (xh == 0.5)
{ {
if (xl > 0.0 || (xl == 0.0 && res >= 0)) if (xl > 0.0 || (xl == 0.0 && res >= 0))
res += 1; if (__glibc_unlikely (__builtin_add_overflow (res, 1, &res)))
goto overflow;
} }
else if (-xh > 0.5) else if (-xh > 0.5)
{ {
res -= 1; if (__glibc_unlikely (__builtin_add_overflow (res, -1, &res)))
goto overflow;
} }
else if (-xh == 0.5) else if (-xh == 0.5)
{ {
if (xl < 0.0 || (xl == 0.0 && res <= 0)) if (xl < 0.0 || (xl == 0.0 && res <= 0))
res -= 1; if (__glibc_unlikely (__builtin_add_overflow (res, -1, &res)))
goto overflow;
} }
if (__glibc_unlikely (((~(hi ^ (res - hi)) & (res ^ hi)) < 0)))
goto overflow;
return res; return res;
} }
else else