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

Java MIDI fails with a dereferenced memory error when asked to send a raw 0xF7

    XMLWordPrintable

    Details

    • Subcomponent:
    • Resolved In Build:
      b24
    • CPU:
      x86_64
    • OS:
      windows_10

      Backports

        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


          Attachments

            Issue Links

              Activity

                People

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

                  Dates

                  Created:
                  Updated:
                  Resolved: