JDK-8237495 : Java MIDI fails with a dereferenced memory error when asked to send a raw 0xF7
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.sound
  • Affected Version: 8,11,13,14,15
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_10
  • CPU: x86_64
  • Submitted: 2020-01-14
  • Updated: 2023-12-06
  • Resolved: 2020-11-11
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 16 Other
11.0.11-oracleFixed 16 b24Fixed openjdk8u312Fixed
Related Reports
Relates :  
Description
ADDITIONAL SYSTEM INFORMATION :
All Windows and Linux installations I have tested on.

A DESCRIPTION OF THE PROBLEM :
Some synthesizers (notably the Casio CZ series and the Yamaha TG33, SY22, and SY35) require that you send a sysex message not all at once but piecemeal, separated by delays.  The standard Java sysex class only sends whole messages at a time, but it is easy -- and appropriate -- to create a message class which allows you to send arbitrary data as needed.  However if you use this class to send a single 0xF7 (the value which indicates the end of a sysex message), the virtual machine will bomb hard in Windows and in Linux.  This is not the case on the Mac because (1) MacOS Java is broken with regard to sysex in the first place and (2) everyone on the Mac who does MIDI Java uses the superior CoreMidi4J library anyway, and this library has no problem with 0xF7.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Create a subclass of javax.sound.midi.MidiMessage which permits you to send arbitrary bytes in the stream.
2. Use this message subclass to send a single 0xF7.
3. All Windows implementations and all current Linux implementations will fail.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
An 0xF7 is sent out the MIDI stream.
ACTUAL -
VM fails with a report of accessing deallocated memory.

---------- BEGIN SOURCE ----------
import javax.sound.midi.*;
import java.util.*;

public class Send
	{
	public static class RawMidiMessage extends MidiMessage
		{
		public Object clone() 
			{
			return new RawMidiMessage(getMessage());
			}
		
		public int getStatus() { return 0xF0; }   // not that this really matters
	
		public RawMidiMessage(byte[] data)
			{
			super(data.clone());
			}
		}
		
	public static void main(String[] args) throws Exception
		{
		MidiDevice.Info[] infos;
		
            infos = MidiSystem.getMidiDeviceInfo();

		for(int i = 0; i < infos.length; i++)
			{
			System.err.println("" + i + "\t" + infos[i]);
			}
		int dev = 4;	// For me, that's MIDI Monitor
		MidiDevice device = MidiSystem.getMidiDevice(infos[dev]);		// or pick an appropriate device
		System.err.println("Sending to " + device + " ( " + infos[dev] + ")");
		if (!device.isOpen()) device.open();
		Receiver r = device.getReceiver();
		System.err.println("note on");
		r.send(new ShortMessage(ShortMessage.NOTE_ON, 5, 5), -1);
		System.err.println("sysex");
		r.send(new SysexMessage(new byte[] { (byte)0xF0, 0x0, 0x03, 0x04, (byte)0xF7 }, 5), -1);
		System.err.println("raw 1");
		r.send(new RawMidiMessage(new byte[] { (byte)0x02, 0x02, 0x03, 0x04 }), -1);
		System.err.println("raw 2");
		r.send(new RawMidiMessage(new byte[] { (byte)0x09, 0x02, 0x03, 0x04 }), -1);
		System.err.println("raw 3");
		r.send(new RawMidiMessage(new byte[] { (byte)0xF0, 0x02, 0x03, 0x04 }), -1);
		System.err.println("raw 4");
		r.send(new RawMidiMessage(new byte[] { (byte)0x02, 0x02, 0x03, 0x04 }), -1);
		System.err.println("raw 5");
		r.send(new RawMidiMessage(new byte[] { (byte)0x02, 0x02, 0x03, (byte)0xF7 }), -1);
		System.err.println("raw 6");
		r.send(new RawMidiMessage(new byte[] { (byte)0xF0, 0x02, 0x03, 0x04 }), -1);
		System.err.println("sleep");
		Thread.currentThread().sleep(1000);
		System.err.println("raw 7");
		r.send(new RawMidiMessage(new byte[] { (byte)0x02, 0x02, 0x03, 0x04 }), -1);
		System.err.println("sleep");
		Thread.currentThread().sleep(1000);
		System.err.println("raw 8");
		r.send(new RawMidiMessage(new byte[] { (byte) (byte)0xF7 }), -1);
		System.err.println("note off");
		r.send(new ShortMessage(ShortMessage.NOTE_OFF, 5, 5), -1);
		System.err.println("done, should quit");
		}
	}

---------- END SOURCE ----------

FREQUENCY : always



Comments
Fix Request (8u) This change fixes the crash when some specially crafted midi message is sent to the audio card. It was not proved that it is possible to provoke the crash via playing the midi file, but to be safe I suggest making a backport. Code review: https://mail.openjdk.java.net/pipermail/jdk8u-dev/2021-August/014150.html
06-08-2021

Fix Request Should get backported for parity with 11.0.11-oracle. Applies cleanly.
28-12-2020

Changeset: 5de99da7 Author: Sergey Bylokhov <serb@openjdk.org> Date: 2020-11-11 01:31:03 +0000 URL: https://github.com/openjdk/jdk/commit/5de99da7
11-11-2020

Per description, Java MIDI fails with a dereferenced memory error when asked to send a raw 0xF7. Issue is reproducible with JDk 8 as well as 14 and 15 ea. Result: =========== 8: Fail 8u241: Fail 14: Fail 15 ea b06: Fail To verify, run the attached test case with respective JDk versions.
18-01-2020