1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

VSTMidiEventList: Avoid UB Sanitizer warnings about out-of-bounds VLA access

This commit is contained in:
reuk 2021-09-20 13:06:14 +01:00
parent afa6465098
commit 3a1be39cb6
No known key found for this signature in database
GPG key ID: 9ADCD339CFC98A11

View file

@ -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;