JDK-8179678 : ArrayCopy with same src and dst can cause incorrect execution or compiler crash
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 9
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2017-05-05
  • Updated: 2019-09-13
  • Resolved: 2017-06-02
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 10 JDK 9
10Fixed 9 b173Fixed
Related Reports
Relates :  
Relates :  
Description
public class TestACSameSrcDst {
    static int test1(int[] src, int[] dst) {
        System.arraycopy(src, 5, dst, 0, 10);
        return dst[0];
    }

    static int test2(int[] src) {
        System.arraycopy(src, 0, src, 0, 10);
        return src[0];
    }

    public static void main(String[] args) {
        int[] array = new int[15];
        for (int i = 0; i < 20000; i++) {
            for (int j = 0; j < array.length; j++) {
                array[j] = j;
            }
            int expected = array[5];
            int res = test1(array, array);
            if (res != expected) {
                throw new RuntimeException("bad result: " + res + " != " + expected);
            }
            test2(array);
        }
    }
}

test1() above causes an incorrect execution. test2() causes an infinite loop in GVN:

#  Internal Error (/home/roland/hs/hotspot/src/share/vm/opto/phaseX.cpp:791), pid=6855, tid=6892
#  assert(loop_count++ < K) failed: infinite loop in PhaseGVN::transform

Both are caused by LoadNode::can_see_arraycopy_value()


Comments
Approved for JDK 9.
01-06-2017

All tests passed. [~kvn], [~iignatyev] please approve the fix request.
01-06-2017

Fix Request Fixing this is critical because it can lead to incorrect code execution or a VM crash. The proposed fix is to have C2 proceed with the currently broken optimization only if it can prove that the arraycopy can't overwrite the range of the source array being copied In the process of fixing this, I found other bugs and the change is now of medium size. I would say risk is low to medium. I tested this with java/lang, java/util and hotspot jtreg tests with -Xcomp and -Xcomp -XX:-ReduceInitialCardMarks Change was reviewed by Tobias and Vladimir K Fix: http://cr.openjdk.java.net/~roland/8179678/webrev.04/
31-05-2017

Okay, thanks. We should fix this in JDK 9 then.
05-05-2017

I would say it's been broken since I pushed the code for LoadNode::can_see_arraycopy_value(): changeset: 8384:c78f961f7edb user: roland date: Tue May 12 10:27:50 2015 +0200 summary: 8076188: Optimize arraycopy out for non escaping destination
05-05-2017

ILW = Crash in compiler or incorrect execution, easy to reproduce but uncommon code, disable compilation = HMM = P2 Roland, is this a recent regression?
05-05-2017

LoadNode::can_see_arraycopy_value() should verify src and dst of ArrayCopy are not the same.
05-05-2017