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

java.util.random L128X256MixRandom constructor fails to use byte[] seed

    XMLWordPrintable

Details

    • b18
    • generic
    • generic
    • Verified

    Description

      A DESCRIPTION OF THE PROBLEM :
      The L128X256MixRandom(byte[]) constructor converts the byte[] to a long[]. The required state size is 8 longs. The current code uses 6 longs. The result is an ArrayIndexOutOfBoundsException is thrown by the byte[] constructor.

      This code:

      // Convert the seed to 6 long values, of which the last 4 are not all zero.
      long[] data = RandomSupport.convertSeedBytesToLongs(seed, 6, 4);

      Should be:

      // Convert the seed to 8 long values, of which the last 4 are not all zero.
      long[] data = RandomSupport.convertSeedBytesToLongs(seed, 8, 4);


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      This does not readily manifest in code. The RandomGeneratorFactory creates the generator using a try-catch block:

          public T create(byte[] seed) {
              Objects.requireNonNull(seed, "seed must not be null");
              try {
                  ensureConstructors();
                  return ctorBytes.newInstance(seed);
              } catch (Exception ex) {
                  return create();
              }
          }

      The ArrayIndexOutOfBoundsException is caught and a default generator is constructed.

      The generator should be the same when the same seed is used:

      import java.util.random.*;

      public class L128X256MixRandomBug {
        public static void main(String[] args) {

          byte[] seed = {1, 2, 3, 4, 5};

          for (String name : new String[]{
            "L32X64MixRandom",
            "L64X128StarStarRandom",
            "L64X128MixRandom",
            "L64X256MixRandom",
            "L64X1024MixRandom",
            "L128X128MixRandom",
            "L128X256MixRandom",
            "L128X1024MixRandom",
          }) {
            // This should be reproducible
            RandomGenerator g1 = RandomGeneratorFactory.of(name).create(seed);
            RandomGenerator g2 = RandomGeneratorFactory.of(name).create(seed);

            System.out.printf("%-21s is reproducible %b%n", name,
              g1.nextLong() == g2.nextLong());
          }
        }
      }

      With access to the internal class it should be simple to show that:

      // any byte[] length should fail
      new L128X256MixRandom(new byte[3])

      will throw an ArrayIndexOutOfBoundsException.


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      > java L128X256MixRandomBug
      L32X64MixRandom is reproducible true
      L64X128StarStarRandom is reproducible true
      L64X128MixRandom is reproducible true
      L64X256MixRandom is reproducible true
      L64X1024MixRandom is reproducible true
      L128X128MixRandom is reproducible true
      L128X256MixRandom is reproducible true
      L128X1024MixRandom is reproducible true
      ACTUAL -
      > java L128X256MixRandomBug
      L32X64MixRandom is reproducible true
      L64X128StarStarRandom is reproducible true
      L64X128MixRandom is reproducible true
      L64X256MixRandom is reproducible true
      L64X1024MixRandom is reproducible true
      L128X128MixRandom is reproducible true
      L128X256MixRandom is reproducible false
      L128X1024MixRandom is reproducible true

      ---------- BEGIN SOURCE ----------
      Driver program provided.
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      None. The user will be unaware that the input byte[] has been ignored and a default instance was returned.


      FREQUENCY : always


      Attachments

        Issue Links

          Activity

            People

              rgiulietti Raffaello Giulietti
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: