eclipse-openj9 / openj9

Eclipse OpenJ9: A Java Virtual Machine for OpenJDK that's optimized for small footprint, fast start-up, and high throughput. Builds on Eclipse OMR (https://github.com/eclipse/omr) and combines with the Extensions for OpenJDK for OpenJ9 repo.
Other
3.23k stars 712 forks source link

ClassFormatError is not reported properly in OpenJ9 #19125

Open TemporaryRepos opened 3 months ago

TemporaryRepos commented 3 months ago

Affected versions

We found a test case with execution problems. To facilitate analysis, we simplified the test case and the simplified class file can ben found at attachment.

Linux Ubuntu20.04

Java -version output under Linux

openjdk version "1.8.0_402"
IBM Semeru Runtime Open Edition (build 1.8.0_402-b06)
Eclipse OpenJ9 VM (build openj9-0.43.0, JRE 1.8.0 Linux amd64-64-Bit Compressed References 20240131_861 (JIT enabled, AOT enabled)
OpenJ9   - 2c3d78b48
OMR      - ea8124dbc
JCL      - 0fa9d9c532 based on jdk8u402-b06)
openjdk version "11.0.22" 2024-01-16
IBM Semeru Runtime Open Edition 11.0.22.0 (build 11.0.22+7)
Eclipse OpenJ9 VM 11.0.22.0 (build openj9-0.43.0, JRE 11 Linux amd64-64-Bit Compressed References 20240131_966 (JIT enabled, AOT enabled)
OpenJ9   - 2c3d78b48
OMR      - ea8124dbc
JCL      - 7876cac747 based on jdk-11.0.22+7)
openjdk version "17.0.10" 2024-01-16
IBM Semeru Runtime Open Edition 17.0.10.0 (build 17.0.10+7)
Eclipse OpenJ9 VM 17.0.10.0 (build openj9-0.43.0, JRE 17 Linux amd64-64-Bit Compressed References 20240116_670 (JIT enabled, AOT enabled)
OpenJ9   - 2c3d78b48
OMR      - ea8124dbc
JCL      - 2aad089841f based on jdk-17.0.10+7)

Problem summary

TestCase8 invoked in the vm.mlvm.share.CustomClassLoaders, because c>6=D is an incorrect class name, so Hotspot reports a ClassFormatError. However, no information is reported when executed with OpenJ9.

Steps to Reproduce

java-8/bin/java TestCase8

Expected Result

ClassFormatError

Actual Result

nothing

Attachment

202403122309.zip

pshipton commented 3 months ago

@tajila fyi

ChengJin01 commented 3 months ago

There should be a couple of cases in verifying the class name above in terms of the qualification.

@TemporaryRepos, could you provide the following cases as to how it goes with Hotspot ? 1) class name = c>6 2) class name = c<6 3) class name = c<>6 4) class name = c6=D

My understanding is that either < or > or both of them should be accepted as valid against the JVM Spec.

TemporaryRepos commented 3 months ago

This is our hotspot version

openjdk version "1.8.0_402"
OpenJDK Runtime Environment (Temurin)(build 1.8.0_402-b06)
OpenJDK 64-Bit Server VM (Temurin)(build 25.402-b06, mixed mode)

openjdk version "11.0.22" 2024-01-16
OpenJDK Runtime Environment Temurin-11.0.22+7 (build 11.0.22+7)
OpenJDK 64-Bit Server VM Temurin-11.0.22+7 (build 11.0.22+7, mixed mode)

openjdk version "17.0.10" 2024-01-16
OpenJDK Runtime Environment Temurin-17.0.10+7 (build 17.0.10+7)
OpenJDK 64-Bit Server VM Temurin-17.0.10+7 (build 17.0.10+7, mixed mode, sharing)
TemporaryRepos commented 3 months ago

if classname = 'c>6=D' hotspot8 -> ClassFormatError hotspot11 -> IllegalAccessError hotspot17 -> ClassFormatError

if classname = 'c>6' || 'c<6' || 'c<>6' || 'c6=D' hotspot8 -> ClassNotFoundException hotspot11 -> IllegalAccessError hotspot17 -> ClassNotFoundException

@ChengJin01

ChengJin01 commented 3 months ago

if classname = 'c>6' || 'c<6' || 'c<>6' || 'c6=D' hotspot8 -> ClassNotFoundException hotspot11 -> IllegalAccessError hotspot17 -> ClassNotFoundException

Assuming there is an invalid character (> or =) captured as invalid for the class name on JDK8/17, it doesn't make any sense to me that it ended up ClassNotFoundException with the class names above on JDK8/17 (which means nothing goes wrong in validating the class name c>6=D).

@TemporaryRepos, please double-check your updated test cases to see what happened to your changes as everything related to the class name should be modified to keep consistent with the code, including the bytecode generated with the ASM tools at runtime:

  static void test_cp_oppos(int[], int[], float[], float[]);
    descriptor: ([I[I[F[F)V
    flags: (0x0008) ACC_STATIC
    Code:
      stack=7, locals=4, args_size=4
         0: new           #20                 // class jdk/internal/org/objectweb/asm/ClassWriter
         3: astore_0
         4: aload_0
         5: iconst_0
         6: invokespecial #23                 // Method jdk/internal/org/objectweb/asm/ClassWriter."<init>":(I)V
         9: aload_0
        10: ldc           #24                 // int 196653
        12: iconst_1
        13: ldc           #26                 // String c>6=D
        15: aconst_null
        16: ldc           #27                 // String java/lang/Object
        18: aconst_null
        19: invokevirtual #31                 // Method jdk/internal/org/objectweb/asm/ClassWriter.visit:(IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V
        22: aload_0
        23: invokevirtual #35                 // Method jdk/internal/org/objectweb/asm/ClassWriter.toByteArray:()[B
<------ the class bytecode was generated at runtime

otherwise, it would still end up with ClassNotFoundException even though the class name is changed to c6D (which is totally valid).