From 3a1be39cb66ac877cb3ce00e04b82ccb7f79bc16 Mon Sep 17 00:00:00 2001 From: reuk Date: Mon, 20 Sep 2021 13:06:14 +0100 Subject: [PATCH] VSTMidiEventList: Avoid UB Sanitizer warnings about out-of-bounds VLA access --- .../format_types/juce_VSTMidiEventList.h | 37 ++++++++++++++----- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/modules/juce_audio_processors/format_types/juce_VSTMidiEventList.h b/modules/juce_audio_processors/format_types/juce_VSTMidiEventList.h index 7e20828923..4bb2062846 100644 --- a/modules/juce_audio_processors/format_types/juce_VSTMidiEventList.h +++ b/modules/juce_audio_processors/format_types/juce_VSTMidiEventList.h @@ -39,6 +39,22 @@ namespace juce */ class VSTMidiEventList { + // "events" is expected to be a const- or non-const-ref to Vst2::VstEvents. + template + 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 (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 (ptr); + if (e->type == Vst2::kVstSysExType) { - delete[] (((Vst2::VstMidiSysexEvent*) ptr)->sysexDump); + delete[] reinterpret_cast (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 (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 (ptr)->midiData, 4, e->deltaFrames); } else if (e->type == Vst2::kVstSysExType) { - const auto* se = (const Vst2::VstMidiSysexEvent*) ptr; + const auto* se = static_cast (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;