Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Dragonwell (1.8.0_275): getMessage() for an ArrayIndexOutOfBoundsException instance is null #186

Closed
fuzzy000 opened this issue Jan 21, 2021 · 2 comments

Comments

@fuzzy000
Copy link

Description
We made some changes to a class file in the Apache Ant project, and let several JVMs execute the corresponding JUnit test. We found that in the test case testParse in ExtraFieldUtilsTest, Dragonwell (11.0.9) threw an org.junit.ComparisonFailure while Dragonwell (1.8.0_275) threw a java.lang.AssertionError:

Dragonwell (1.8.0_275):

testParse(org.apache.tools.zip.ExtraFieldUtilsTest)
java.lang.AssertionError: message expected:<bad extra field starting at 18.  Block length of 1 bytes exceeds remaining data of 0 bytes.> but was:<null>
        at org.junit.Assert.fail(Assert.java:88)
        at org.junit.Assert.failNotEquals(Assert.java:834)
        at org.junit.Assert.assertEquals(Assert.java:118)
        at org.apache.tools.zip.ExtraFieldUtilsTest.testParse(ExtraFieldUtilsTest.java:96)
        ...

Dragonwell (11.0.9):

testParse(org.apache.tools.zip.ExtraFieldUtilsTest)
org.junit.ComparisonFailure: message expected:<[bad extra field starting at 18.  Block length of 1 bytes exceeds remaining data of 0 bytes.]> but was:<[arraycopy: last source index 23 out of bounds for byte[22]]>
        at org.junit.Assert.assertEquals(Assert.java:115)
        at org.apache.tools.zip.ExtraFieldUtilsTest.testParse(ExtraFieldUtilsTest.java:96)
        ...

After inspecting into the source code of JUnit, we found the JVM just executed the different path in the method assertEquals of org.junit.Assert(junit-4.12.jar):

    static public void assertEquals(String message, Object expected,
            Object actual) {
        if (equalsRegardingNull(expected, actual)) {
            return;
        } else if (expected instanceof String && actual instanceof String) {
            String cleanMessage = message == null ? "" : message;
            throw new ComparisonFailure(cleanMessage, (String) expected, (String) actual);  // Dragonwell (11.0.9) executed this line
        } else {
            failNotEquals(message, expected, actual);  // Dragonwell (1.8.0_275) executed this line
        }
    }

Then I add several print statement in the ExtraFieldUtilsTest.java to debug:

    @Test
    public void testParse() throws Exception {
        ZipExtraField[] ze = ExtraFieldUtils.parse(data);
        assertEquals("number of fields", 2, ze.length);
        assertTrue("type field 1", ze[0] instanceof AsiExtraField);
        assertEquals("mode field 1", 040755,
                     ((AsiExtraField) ze[0]).getMode());
        assertTrue("type field 2", ze[1] instanceof UnrecognizedExtraField);
        assertEquals("data length field 2", 1,
                     ze[1].getLocalFileDataLength().getValue());

        byte[] data2 = new byte[data.length - 1];
        System.arraycopy(data, 0, data2, 0, data2.length);
        try {
            ExtraFieldUtils.parse(data2);
            fail("data should be invalid");
        } catch (Exception e) {
            System.out.println(data2);
            System.out.println(e);
            System.out.println(e==null);
            System.out.println(e.getMessage());
            e.printStackTrace();
            assertEquals("message",
                         "bad extra field starting at " + (4 + aLocal.length)
                         + ".  Block length of 1 bytes exceeds remaining data of 0 bytes.",
                         e.getMessage());
        }
    }

I found that for Dragonwell (1.8.0_275), e.getMessage() returns null, while e.getMessage() of Dragonwell (11.0.9) returns arraycopy: last source index 23 out of bounds for byte[22]. But e.getMessage() should not be null.

Steps to Reproduce
Steps to reproduce the behavior:

  1. Download DifferentExecutionPath.zip
  2. extract the DifferentExecutionPath.zip
  3. In directory DifferentExecutionPath, run command java -cp sootOutput/junit-ant/:hamcrest-core-1.3.jar:junit-4.12.jar org.junit.runner.JUnitCore org.apache.tools.zip.ExtraFieldUtilsTest

Expected behavior
Dragonwell (1.8.0_275) is expected to throw ComparisonFailure.
e.getMessage() for Dragonwell (1.8.0_275) should be a non-null value.

JDK version
dw8:

openjdk version "1.8.0_275"
OpenJDK Runtime Environment (Alibaba Dragonwell 8.5.5) (build 1.8.0_275-b2)
OpenJDK 64-Bit Server VM (Alibaba Dragonwell 8.5.5) (build 25.275-b2, mixed mode)

dw11:

openjdk version "11.0.9" 2020-10-20
OpenJDK Runtime Environment (Alibaba Dragonwell) (build 11.0.9+0)
OpenJDK 64-Bit Server VM (Alibaba Dragonwell) (build 11.0.9+0, mixed mode)

Execution environment

  • OS and version: Ubuntu 16.04.6 LTS
  • CPU model: Intel(R) Xeon(R) CPU E5-4610 v4 @ 1.80GHz
  • Number of CPU cores: 4CPUs, each has 10 cores
  • Size of physical memory: 16384 MB * 20
@fuzzy000
Copy link
Author

Also, this bug also happens in the corresponding versions of OpenJDK which is confirmed by OpenJDK developers: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8259961

@tianxiaogu
Copy link
Contributor

Thanks a lot for the bug report. Note that the bug report at https://bugs.openjdk.java.net/browse/JDK-8259961 is still unresolved. The OpenJDK developers only confirmed that the issue is reproducible.

This issue is indeed not a bug. According to Java core libraries documents (https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Throwable.html#getMessage() and https://docs.oracle.com/javase/8/docs/api/java/lang/Throwable.html#getMessage--), the return value ofgetMessage is not fully specified, which means a programmer should not rely on its value.

Please report this issue as a test case bug to Apache Ant. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants