[gcc(refs/users/marxin/heads/marxin-gcc-benchmark-branch)] sccvn: Fix buffer overflow in push_partial_def [PR94300]

Martin Liska marxin@gcc.gnu.org
Mon Mar 30 11:05:37 GMT 2020


https://gcc.gnu.org/g:f1154b4d3c54e83d493cc66d1a30c410b9b3108a

commit f1154b4d3c54e83d493cc66d1a30c410b9b3108a
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Wed Mar 25 09:17:01 2020 +0100

    sccvn: Fix buffer overflow in push_partial_def [PR94300]
    
    The following testcase is miscompiled, because there is a buffer overflow
    in push_partial_def in the little-endian case when working 64-byte vectors.
    The code computes the number of bytes we need in the BUFFER: NEEDED_LEN,
    which is rounded up number of bits we need.  Then the code
    native_encode_expr each (partially overlapping) pd into THIS_BUFFER.
    If pd.offset < 0, i.e. the pd.rhs store starts at some bits before the
    window we are interested in, we pass -pd.offset to native_encode_expr and
    shrink the size already earlier:
          HOST_WIDE_INT size = pd.size;
          if (pd.offset < 0)
            size -= ROUND_DOWN (-pd.offset, BITS_PER_UNIT);
    On this testcase, the problem is with a store with pd.offset > 0,
    in particular pd.offset 256, pd.size 512, i.e. a 64-byte store which doesn't
    fit into entirely into BUFFER.
    We have just:
              size = MIN (size, (HOST_WIDE_INT) needed_len * BITS_PER_UNIT);
    in this case for little-endian, which isn't sufficient, because needed_len
    is 64, the entire BUFFER (except of the last extra byte used for shifting).
    native_encode_expr fills the whole THIS_BUFFER (again, except the last extra
    byte), and the code then performs memcpy (BUFFER + 32, THIS_BUFFER, 64);
    which overflows BUFFER and as THIS_BUFFER is usually laid out after it,
    overflows it into THIS_BUFFER.
    The following patch fixes it by for pd.offset > 0 making sure size is
    reduced too.  For big-endian the code does things differently and already
    handles this right.
    
    2020-03-25  Jakub Jelinek  <jakub@redhat.com>
    
            PR tree-optimization/94300
            * tree-ssa-sccvn.c (vn_walk_cb_data::push_partial_def): If pd.offset
            is positive, make sure that off + size isn't larger than needed_len.
    
            * gcc.target/i386/avx512f-pr94300.c: New test.

Diff:
---
 gcc/ChangeLog                                   |  6 ++++++
 gcc/testsuite/ChangeLog                         |  3 +++
 gcc/testsuite/gcc.target/i386/avx512f-pr94300.c | 21 +++++++++++++++++++++
 gcc/tree-ssa-sccvn.c                            |  2 ++
 4 files changed, 32 insertions(+)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 485fc09464a..4a0e473afd7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2020-03-25  Jakub Jelinek  <jakub@redhat.com>
+
+	PR tree-optimization/94300
+	* tree-ssa-sccvn.c (vn_walk_cb_data::push_partial_def): If pd.offset
+	is positive, make sure that off + size isn't larger than needed_len.
+
 2020-03-25  Richard Biener  <rguenther@suse.de>
 	    Jakub Jelinek  <jakub@redhat.com>
 
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5a428085aab..2a39af6feab 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,8 @@
 2020-03-25  Jakub Jelinek  <jakub@redhat.com>
 
+	PR tree-optimization/94300
+	* gcc.target/i386/avx512f-pr94300.c: New test.
+
 	PR debug/94283
 	* gcc.dg/pr94283.c: New test.
 
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-pr94300.c b/gcc/testsuite/gcc.target/i386/avx512f-pr94300.c
new file mode 100644
index 00000000000..7593408dae9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-pr94300.c
@@ -0,0 +1,21 @@
+/* PR tree-optimization/94300 */
+/* { dg-do run { target { avx512f } } } */
+/* { dg-options "-O1 -mavx512f -mprefer-vector-width=512 -mtune=skylake-avx512" } */
+
+#include "avx512f-check.h"
+
+typedef double V __attribute__((vector_size (64)));
+
+static void
+avx512f_test (void)
+{
+  double mem[16];
+  const V a = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0 };
+  const V b = { 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0 };
+  V c;
+  __builtin_memcpy (mem, &a, 64);
+  __builtin_memcpy (mem + 8, &b, 64);
+  __builtin_memcpy (&c, mem + 4, 64);
+  if (c[5] != 9.0)
+    __builtin_abort ();
+}
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 150ddad3e69..fd74809ca6e 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -2058,6 +2058,8 @@ vn_walk_cb_data::push_partial_def (pd_data pd,
 		shift_bytes_in_array_left (this_buffer, len + 1, amnt);
 	      unsigned int off = pd.offset / BITS_PER_UNIT;
 	      gcc_assert (off < needed_len);
+	      size = MIN (size,
+			  (HOST_WIDE_INT) (needed_len - off) * BITS_PER_UNIT);
 	      p = buffer + off;
 	      if (amnt + size < BITS_PER_UNIT)
 		{


More information about the Gcc-cvs mailing list