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

FastSysexMessage constructor crashes MIDI receiption thread

XMLWordPrintable

    • b17
    • x86_64
    • windows_7

        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


              serb Sergey Bylokhov
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Created:
                Updated:
                Resolved: