VST3 hosting: use-after-free in MidiEventList::toEventList


When SysEx messages are received, the VST3 function toEventList is handling incorrectly the memory at this line:

    else if (msg.isSysEx())
        e.type          = Steinberg::Vst::Event::kDataEvent;
        e.data.bytes    = msg.getSysExData();
        e.data.size     = (uint32) msg.getSysExDataSize();
        e.data.type     = Steinberg::Vst::DataEvent::kMidiSysEx;

because the e.data.bytes data was allocated when msg was created, and is released when msg is assigned to the next midi event of the buffer. This is causing a use-after-free bug when the data is received by the VST3 plugin.

I’m not seeing any use-after-free crashes when testing this, and looking at the MidiBuffer::Iterator::getNextEvent() internals it looks like the data pointer will be pointing directly to the MidiBuffer's internal data, so should outlive the local MidiMessage object.

It would be helpful if you could post a simple test to reproduce this.

It is using this getNextEvent function:

bool MidiBuffer::Iterator::getNextEvent (MidiMessage& result, int& samplePosition) noexcept

which is building the MidiMessage with

result = MidiMessage (data + sizeof (int32) + sizeof (uint16), itemSize, samplePosition);

You can check that this constructor of MidiMessage ends with an allocation of memory:

memcpy (allocateSpace (dataSize), d, (size_t) dataSize);

So the MidiMessage holds the sysex content, and this contents will be deallocated on the next getNextEvent call when the MidiMessage is reassign to another event. It does not hold a pointer into the MidiBuffer data.

If you want to reproduce that, build the PluginHost with address sanitizer , load a VST3, and send any SysEx (of more than 4 bytes) event into the PluginHost MIDI port.

Ah yes, you’re right sorry. I’ll push something for this.