Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8231490

Ugly racy writes to ZipUtils.defaultBuf

XMLWordPrintable

      java tsan reported a race like the below for jdk11:

      WARNING: ThreadSanitizer: data race (pid=1157)
        Read of size 4 at 0x0000cf912c30 by thread T21 (mutexes: write M393783495844463056, write M180524):
          #0 java.nio.Buffer.position()I Buffer.java:275
          #1 java.util.zip.Inflater.inflate([BII)I Inflater.java:393
          #2 java.util.zip.InflaterInputStream.read([BII)I InflaterInputStream.java:153
          #3 jdk.internal.loader.Resource.getBytes()[B Resource.java:124
          #4 jdk.internal.loader.BuiltinClassLoader.defineClass(Ljava/lang/String;Ljdk/internal/loader/Resource;)Ljava/lang/Class; BuiltinClassLoader.java:799
          #5 jdk.internal.loader.BuiltinClassLoader$4.run()Ljava/lang/Class; BuiltinClassLoader.java:713
          #6 jdk.internal.loader.BuiltinClassLoader$4.run()Ljava/lang/Object; BuiltinClassLoader.java:708
          #7 (Generated Stub) <null>
          #8 jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(Ljava/lang/String;)Ljava/lang/Class; BuiltinClassLoader.java:721
          #9 jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(Ljava/lang/String;Z)Ljava/lang/Class; BuiltinClassLoader.java:623
          #10 jdk.internal.loader.BuiltinClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class; BuiltinClassLoader.java:581
          #11 jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class; ClassLoaders.java:182
          #12 java.lang.ClassLoader.loadClass(Ljava/lang/String;)Ljava/lang/Class; ClassLoader.java:521
      ...


        Previous write of size 4 at 0x0000cf912c30 by thread T7 (mutexes: write M398568570448532384, write M410953469422220392):
          #0 java.nio.Buffer.position(I)Ljava/nio/Buffer; Buffer.java:294
          #1 java.nio.ByteBuffer.position(I)Ljava/nio/ByteBuffer; ByteBuffer.java:1086
          #2 java.util.zip.Inflater.inflate([BII)I Inflater.java:434
          #3 java.util.zip.InflaterInputStream.read([BII)I InflaterInputStream.java:153
          #4 jdk.internal.loader.Resource.getBytes()[B Resource.java:124
          #5 jdk.internal.loader.BuiltinClassLoader.defineClass(Ljava/lang/String;Ljdk/internal/loader/Resource;)Ljava/lang/Class; BuiltinClassLoader.java:799
          #6 jdk.internal.loader.BuiltinClassLoader$4.run()Ljava/lang/Class; BuiltinClassLoader.java:713
          #7 jdk.internal.loader.BuiltinClassLoader$4.run()Ljava/lang/Object; BuiltinClassLoader.java:708
      ...

      Analysis is that every InflaterInputStream starts out with the zero-size but mutable ZipUtils.defaultBuf as its initial input. The first attempt to read from the input will always read zero bytes, but will always update defaultBuf's position (to the same value!) in the first attempt to read.

      It would be better if we did away with the defaultBuf kludge, replacing it with explicit null checks, or if we kept it, made it a read-only byte buffer to prevent concurrent racy writes.

            emcmanus Eamonn McManus
            martin Martin Buchholz
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved: