0d8b67
Based on the following commit, but modified for rhel-7.9.
0d8b67
Added sysdeps/ieee754/ldbl-96/Makefile to contain test case.
0d8b67
Adjust test case to use #include <math_private.h>.
0d8b67
0d8b67
commit 9333498794cde1d5cca518badf79533a24114b6f
0d8b67
Author: Joseph Myers <joseph@codesourcery.com>
0d8b67
Date:   Wed Feb 12 23:31:56 2020 +0000
0d8b67
0d8b67
    Avoid ldbl-96 stack corruption from range reduction of pseudo-zero (bug 25487).
0d8b67
0d8b67
    Bug 25487 reports stack corruption in ldbl-96 sinl on a pseudo-zero
0d8b67
    argument (an representation where all the significand bits, including
0d8b67
    the explicit high bit, are zero, but the exponent is not zero, which
0d8b67
    is not a valid representation for the long double type).
0d8b67
0d8b67
    Although this is not a valid long double representation, existing
0d8b67
    practice in this area (see bug 4586, originally marked invalid but
0d8b67
    subsequently fixed) is that we still seek to avoid invalid memory
0d8b67
    accesses as a result, in case of programs that treat arbitrary binary
0d8b67
    data as long double representations, although the invalid
0d8b67
    representations of the ldbl-96 format do not need to be consistently
0d8b67
    handled the same as any particular valid representation.
0d8b67
0d8b67
    This patch makes the range reduction detect pseudo-zero and unnormal
0d8b67
    representations that would otherwise go to __kernel_rem_pio2, and
0d8b67
    returns a NaN for them instead of continuing with the range reduction
0d8b67
    process.  (Pseudo-zero and unnormal representations whose unbiased
0d8b67
    exponent is less than -1 have already been safely returned from the
0d8b67
    function before this point without going through the rest of range
0d8b67
    reduction.)  Pseudo-zero representations would previously result in
0d8b67
    the value passed to __kernel_rem_pio2 being all-zero, which is
0d8b67
    definitely unsafe; unnormal representations would previously result in
0d8b67
    a value passed whose high bit is zero, which might well be unsafe
0d8b67
    since that is not a form of input expected by __kernel_rem_pio2.
0d8b67
0d8b67
    Tested for x86_64.
0d8b67
0d8b67
diff -urN a/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c b/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c
0d8b67
--- a/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c	2012-12-24 22:02:13.000000000 -0500
0d8b67
+++ b/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c	2021-01-06 20:39:13.502241328 -0500
0d8b67
@@ -210,6 +210,18 @@
0d8b67
       return 0;
0d8b67
     }
0d8b67
 
0d8b67
+  if ((i0 & 0x80000000) == 0)
0d8b67
+    {
0d8b67
+      /* Pseudo-zero and unnormal representations are not valid
0d8b67
+	 representations of long double.  We need to avoid stack
0d8b67
+	 corruption in __kernel_rem_pio2, which expects input in a
0d8b67
+	 particular normal form, but those representations do not need
0d8b67
+	 to be consistently handled like any particular floating-point
0d8b67
+	 value.  */
0d8b67
+      y[1] = y[0] = __builtin_nanl ("");
0d8b67
+      return 0;
0d8b67
+    }
0d8b67
+
0d8b67
   /* Split the 64 bits of the mantissa into three 24-bit integers
0d8b67
      stored in a double array.  */
0d8b67
   exp = j0 - 23;
0d8b67
diff -urN a/sysdeps/ieee754/ldbl-96/Makefile b/sysdeps/ieee754/ldbl-96/Makefile
0d8b67
--- a/sysdeps/ieee754/ldbl-96/Makefile	1969-12-31 19:00:00.000000000 -0500
0d8b67
+++ b/sysdeps/ieee754/ldbl-96/Makefile	2021-01-06 20:55:49.163141757 -0500
0d8b67
@@ -0,0 +1,22 @@
0d8b67
+# Makefile for sysdeps/ieee754/ldbl-96.
0d8b67
+# Copyright (C) 2016-2021 Free Software Foundation, Inc.
0d8b67
+# This file is part of the GNU C Library.
0d8b67
+
0d8b67
+# The GNU C Library is free software; you can redistribute it and/or
0d8b67
+# modify it under the terms of the GNU Lesser General Public
0d8b67
+# License as published by the Free Software Foundation; either
0d8b67
+# version 2.1 of the License, or (at your option) any later version.
0d8b67
+
0d8b67
+# The GNU C Library is distributed in the hope that it will be useful,
0d8b67
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
0d8b67
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0d8b67
+# Lesser General Public License for more details.
0d8b67
+
0d8b67
+# You should have received a copy of the GNU Lesser General Public
0d8b67
+# License along with the GNU C Library; if not, see
0d8b67
+# <https://www.gnu.org/licenses/>.
0d8b67
+
0d8b67
+ifeq ($(subdir),math)
0d8b67
+tests += test-sinl-pseudo
0d8b67
+CFLAGS-test-sinl-pseudo.c += -fstack-protector-all
0d8b67
+endif
0d8b67
diff -urN a/sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c b/sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c
0d8b67
--- a/sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c	1969-12-31 19:00:00.000000000 -0500
0d8b67
+++ b/sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c	2021-01-05 16:27:24.658596782 -0500
0d8b67
@@ -0,0 +1,41 @@
0d8b67
+/* Test sinl for pseudo-zeros and unnormals for ldbl-96 (bug 25487).
0d8b67
+   Copyright (C) 2020 Free Software Foundation, Inc.
0d8b67
+   This file is part of the GNU C Library.
0d8b67
+
0d8b67
+   The GNU C Library is free software; you can redistribute it and/or
0d8b67
+   modify it under the terms of the GNU Lesser General Public
0d8b67
+   License as published by the Free Software Foundation; either
0d8b67
+   version 2.1 of the License, or (at your option) any later version.
0d8b67
+
0d8b67
+   The GNU C Library is distributed in the hope that it will be useful,
0d8b67
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
0d8b67
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0d8b67
+   Lesser General Public License for more details.
0d8b67
+
0d8b67
+   You should have received a copy of the GNU Lesser General Public
0d8b67
+   License along with the GNU C Library; if not, see
0d8b67
+   <https://www.gnu.org/licenses/>.  */
0d8b67
+
0d8b67
+#include <math.h>
0d8b67
+#include <math_private.h>
0d8b67
+#include <stdint.h>
0d8b67
+
0d8b67
+static int
0d8b67
+do_test (void)
0d8b67
+{
0d8b67
+  for (int i = 0; i < 64; i++)
0d8b67
+    {
0d8b67
+      uint64_t sig = i == 63 ? 0 : 1ULL << i;
0d8b67
+      long double ld;
0d8b67
+      SET_LDOUBLE_WORDS (ld, 0x4141,
0d8b67
+                        sig >> 32, sig & 0xffffffffULL);
0d8b67
+      /* The requirement is that no stack overflow occurs when the
0d8b67
+        pseudo-zero or unnormal goes through range reduction.  */
0d8b67
+      volatile long double ldr;
0d8b67
+      ldr = sinl (ld);
0d8b67
+      (void) ldr;
0d8b67
+    }
0d8b67
+  return 0;
0d8b67
+}
0d8b67
+
0d8b67
+#include <support/test-driver.c>