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

FastSysexMessage constructor crashes MIDI receiption thread

    Details

    • Subcomponent:
    • Resolved In Build:
      b17
    • CPU:
      x86_64
    • OS:
      windows_7

      Description

      A DESCRIPTION OF THE PROBLEM :
      When MIDI is received via USB and the USB device is plugged out or turned off while Sysex message is being sent from the device to the Java application, the com.sun.media.sound.FastSysexMessage constructor causes an ArrayIndexOutOfBoundsException in the thread responsible for MIDI receiption (see below), rendering the whole MIDI receiving infrastructure in the application defunct until app restart.

      The error in the FastSysexMessage is obvious and easy to fix. The broken constructor reads (disassembled from byte code):

      FastSysexMessage(byte[] var1) throws InvalidMidiDataException {
          super(var1);
          if (var1.length == 0 || (var1[0] & 255) != 240 && (var1[0] & 255) != 247) {
              super.setMessage(var1, var1.length);
          }
      }

      The called SysexMessage.setMessage function reads (and obviously doesn't expect an empty data array):

      public void setMessage(byte[] data, int length) throws InvalidMidiDataException {
          int status = (data[0] & 0xFF);
          if ((status != 0xF0) && (status != 0xF7)) {
              throw new InvalidMidiDataException("Invalid status byte for sysex message: 0x" + Integer.toHexString(status));
          }
          super.setMessage(data, length);
      }

      I've successfully fixed the issue by patching the byte code so that the constructor reads:

      FastSysexMessage(byte[] var1) throws InvalidMidiDataException {
          super(var1);
          if (var1.length != 0 && (var1[0] & 255) != 240 && (var1[0] & 255) != 247) {
              super.setMessage(var1, var1.length);
          }
      }

      Since super(var1); sufficiently initializes the message for an empty var1, the setMessage is not needed in this case.



      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Have an application receiving MIDI sysex from a controller (Ableton Push2 in my case, with some firmware modifications to continously send diagnostic sysex). While sysex is underway, turn off or disconnect the controller unit.


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The MIDI receiving thread should survive, incomplete sysex should be ignored. After reconnecting the controller, MIDI should be received from it without restarting the application.
      ACTUAL -
      The MIDI receiption thread crashes. From this moment on, the application cannot receive any more MIDI messages.

      java.lang.ArrayIndexOutOfBoundsException: 0
          at javax.sound.midi.SysexMessage.setMessage(SysexMessage.java:193)
          at com.sun.media.sound.FastSysexMessage.<init>(FastSysexMessage.java:40)
          at com.sun.media.sound.AbstractMidiDevice$TransmitterList.sendMessage(AbstractMidiDevice.java:703)
          at com.sun.media.sound.MidiInDevice.callbackLongMessage(MidiInDevice.java:179)
          at com.sun.media.sound.MidiInDevice.nGetMessages(Native Method)
          at com.sun.media.sound.MidiInDevice.run(MidiInDevice.java:140)
          at java.lang.Thread.run(Thread.java:748)


      CUSTOMER SUBMITTED WORKAROUND :
      No workaround known. The exception cannot be catched by the application programmer as it is occurring in a thread controlled by the java MIDI system.

      FREQUENCY : often


        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                serb Sergey Bylokhov
                Reporter:
                webbuggrp Webbug Group
              • Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: