From 10b6121cb8bcfd7f147c1e502d9c9846b3a7a54a Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Mon, 9 Mar 2020 17:20:15 +0100 Subject: [PATCH] Fix deserialization format of events Apparently it uses VLAs, but in a very sneaky way. --- src/common/serialization.cpp | 12 +++++++----- src/common/serialization.h | 13 +++++++++++-- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/common/serialization.cpp b/src/common/serialization.cpp index ac9baddb..ea102895 100644 --- a/src/common/serialization.cpp +++ b/src/common/serialization.cpp @@ -16,20 +16,22 @@ #include "serialization.h" -#include - DynamicVstEvents::DynamicVstEvents(const VstEvents& c_events) : events(c_events.numEvents) { // Copy from the C-style array into a vector for serialization for (int i = 0; i < c_events.numEvents; i++) { - events[i] = c_events.events[0][i]; + events[i] = *c_events.events[i]; } } VstEvents& DynamicVstEvents::as_c_events() { - // Populate the vst_events struct with data from the vector vst_events.numEvents = events.size(); - vst_events.events[0] = events.data(); + + // Populate the vst_events struct with data from the vector. This will + // overflow past the defined length of `vst_events.events` because it's + // actually a VLA. This is why I put some padding at the end of this struct. + std::transform(events.begin(), events.end(), &vst_events.events[0], + [](VstEvent& event) -> VstEvent* { return &event; }); return vst_events; } diff --git a/src/common/serialization.h b/src/common/serialization.h index da3e685f..20d889e2 100644 --- a/src/common/serialization.h +++ b/src/common/serialization.h @@ -80,9 +80,9 @@ overload(Ts...)->overload; * * Before serialization the events are read from a C-style array into a vector * using this class's constructor, and after deserializing the original struct - * can be obtained again usign the `as_c_events()` method. + * can be reconstructed usign the `as_c_events()` method. */ -class DynamicVstEvents { +class alignas(16) DynamicVstEvents { public: DynamicVstEvents(){}; @@ -107,6 +107,15 @@ class DynamicVstEvents { * vector has been filled. */ VstEvents vst_events; + /** + * The `VstEvents` struct is defined to look like it contains a one or two + * element array of `VstEvent` pointers. The actual truth is that the + * `VstEvents::event` array is actually a variable length array with length + * `VstEvents::numEvents`. This is probably not part of any header files + * because VLAs are not part of any C++ standard. This struct is here to + * make sure there is enough room to copy the elements into. + */ + size_t dummy[max_midi_events]; }; /**