| @@ -39,6 +39,22 @@ namespace juce | |||
| */ | |||
| class VSTMidiEventList | |||
| { | |||
| // "events" is expected to be a const- or non-const-ref to Vst2::VstEvents. | |||
| template <typename Events> | |||
| static auto& getEvent (Events& events, int index) | |||
| { | |||
| using EventType = decltype (&*events.events); | |||
| // We static cast rather than using a direct array index here to circumvent | |||
| // UB sanitizer's bounds-checks. The original struct is supposed to contain | |||
| // a variable-length array, but the declaration uses a size of "2" for this | |||
| // member. | |||
| return static_cast<EventType> (events.events)[index]; | |||
| } | |||
| Vst2::VstEvent* const& getEvent (int index) const { return getEvent (*events, index); } | |||
| Vst2::VstEvent* & getEvent (int index) { return getEvent (*events, index); } | |||
| public: | |||
| //============================================================================== | |||
| VSTMidiEventList() | |||
| @@ -64,15 +80,16 @@ public: | |||
| { | |||
| ensureSize (numEventsUsed + 1); | |||
| void* const ptr = (Vst2::VstMidiEvent*) (events->events [numEventsUsed]); | |||
| auto* const e = (Vst2::VstMidiEvent*) ptr; | |||
| void* const ptr = getEvent (numEventsUsed); | |||
| events->numEvents = ++numEventsUsed; | |||
| if (numBytes <= 4) | |||
| { | |||
| auto* const e = static_cast<Vst2::VstMidiEvent*> (ptr); | |||
| if (e->type == Vst2::kVstSysExType) | |||
| { | |||
| delete[] (((Vst2::VstMidiSysexEvent*) ptr)->sysexDump); | |||
| delete[] reinterpret_cast<Vst2::VstMidiSysexEvent*> (e)->sysexDump; | |||
| e->type = Vst2::kVstMidiType; | |||
| e->byteSize = sizeof (Vst2::VstMidiEvent); | |||
| e->noteLength = 0; | |||
| @@ -86,7 +103,7 @@ public: | |||
| } | |||
| else | |||
| { | |||
| auto* const se = (Vst2::VstMidiSysexEvent*) ptr; | |||
| auto* const se = static_cast<Vst2::VstMidiSysexEvent*> (ptr); | |||
| if (se->type == Vst2::kVstSysExType) | |||
| delete[] se->sysexDump; | |||
| @@ -111,20 +128,20 @@ public: | |||
| { | |||
| for (int i = 0; i < events->numEvents; ++i) | |||
| { | |||
| const Vst2::VstEvent* const e = events->events[i]; | |||
| const auto* const e = getEvent (*events, i); | |||
| if (e != nullptr) | |||
| { | |||
| const void* const ptr = events->events[i]; | |||
| const void* const ptr = e; | |||
| if (e->type == Vst2::kVstMidiType) | |||
| { | |||
| dest.addEvent ((const juce::uint8*) ((const Vst2::VstMidiEvent*) ptr)->midiData, | |||
| dest.addEvent ((const juce::uint8*) static_cast<const Vst2::VstMidiEvent*> (ptr)->midiData, | |||
| 4, e->deltaFrames); | |||
| } | |||
| else if (e->type == Vst2::kVstSysExType) | |||
| { | |||
| const auto* se = (const Vst2::VstMidiSysexEvent*) ptr; | |||
| const auto* se = static_cast<const Vst2::VstMidiSysexEvent*> (ptr); | |||
| dest.addEvent ((const juce::uint8*) se->sysexDump, | |||
| (int) se->dumpBytes, | |||
| e->deltaFrames); | |||
| @@ -148,7 +165,7 @@ public: | |||
| events.realloc (size, 1); | |||
| for (int i = numEventsAllocated; i < numEventsNeeded; ++i) | |||
| events->events[i] = allocateVSTEvent(); | |||
| getEvent (i) = allocateVSTEvent(); | |||
| numEventsAllocated = numEventsNeeded; | |||
| } | |||
| @@ -159,7 +176,7 @@ public: | |||
| if (events != nullptr) | |||
| { | |||
| for (int i = numEventsAllocated; --i >= 0;) | |||
| freeVSTEvent (events->events[i]); | |||
| freeVSTEvent (getEvent (i)); | |||
| events.free(); | |||
| numEventsUsed = 0; | |||