JDK-8221445 : FastSysexMessage constructor crashes MIDI receiption thread
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.sound
  • Affected Version: 8u201,11,13
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_7
  • CPU: x86_64
  • Submitted: 2019-03-14
  • Updated: 2020-02-26
  • Resolved: 2019-04-09
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11 JDK 13
11.0.8-oracleFixed 13 b17Fixed
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



Comments
Fix Request (11u) This solves the problem in javax.sound and keeps codebases in sync (I see 11.0.8-oracle). Patch applies cleanly to 11u, passes tier{1,2,3}, javax/sound/midi tests. New test fails without the product patch.
12-02-2020

Initial report: https://mail.openjdk.java.net/pipermail/sound-dev/2019-March/000668.html
26-03-2019