sccvn: Fix buffer overflow in push_partial_def [PR94300]
authorJakub Jelinek <jakub@redhat.com>
Wed, 25 Mar 2020 08:17:01 +0000 (09:17 +0100)
committerJakub Jelinek <jakub@redhat.com>
Wed, 25 Mar 2020 08:17:01 +0000 (09:17 +0100)
commitf1154b4d3c54e83d493cc66d1a30c410b9b3108a
treefb627b61b79512d67596406e99de8c37fcf3460d
parentc2133167ad58d15c2c2df0cb4fa3a3757603144e
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.
gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/avx512f-pr94300.c [new file with mode: 0644]
gcc/tree-ssa-sccvn.c