From ed056770908a99e088bb630e5dd593a4e26d6406 Mon Sep 17 00:00:00 2001 From: hogliux Date: Mon, 22 May 2017 19:35:45 +0100 Subject: [PATCH] VST2 Hosting: Fixed a memory overrun bug which could occur for plug-ins with more than eight input or output channels --- .../format_types/juce_VSTCommon.h | 74 +++++++++++++++++-- .../format_types/juce_VSTPluginFormat.cpp | 8 +- 2 files changed, 69 insertions(+), 13 deletions(-) diff --git a/modules/juce_audio_processors/format_types/juce_VSTCommon.h b/modules/juce_audio_processors/format_types/juce_VSTCommon.h index 0869c4b8bb..e431051deb 100644 --- a/modules/juce_audio_processors/format_types/juce_VSTCommon.h +++ b/modules/juce_audio_processors/format_types/juce_VSTCommon.h @@ -124,19 +124,77 @@ struct SpeakerMappings : private AudioChannelSet // (inheritance only to give e return vstSpeakerConfigTypeUser; } - static void channelSetToVstArrangement (const AudioChannelSet& channels, VstSpeakerConfiguration& result) + class VstSpeakerConfigurationHolder { - result.type = channelSetToVstArrangementType (channels); - result.numberOfChannels = channels.size(); + public: + VstSpeakerConfigurationHolder () { clear(); } + VstSpeakerConfigurationHolder (const VstSpeakerConfiguration& vstConfig) { operator= (vstConfig); } + VstSpeakerConfigurationHolder (const VstSpeakerConfigurationHolder& other) { operator= (other.get()); } + VstSpeakerConfigurationHolder (VstSpeakerConfigurationHolder&& other) : storage (static_cast&&> (other.storage)) { other.clear(); } - for (int i = 0; i < result.numberOfChannels; ++i) + VstSpeakerConfigurationHolder (const AudioChannelSet& channels) { - VstIndividualSpeakerInfo& speaker = result.speakers[i]; + auto numberOfChannels = channels.size(); + VstSpeakerConfiguration& dst = *allocate (numberOfChannels); - zeromem (&speaker, sizeof (VstIndividualSpeakerInfo)); - speaker.type = getSpeakerType (channels.getTypeOfChannel (i)); + dst.type = channelSetToVstArrangementType (channels); + dst.numberOfChannels = numberOfChannels; + + for (int i = 0; i < dst.numberOfChannels; ++i) + { + VstIndividualSpeakerInfo& speaker = dst.speakers[i]; + + zeromem (&speaker, sizeof (VstIndividualSpeakerInfo)); + speaker.type = getSpeakerType (channels.getTypeOfChannel (i)); + } } - } + + VstSpeakerConfigurationHolder& operator= (const VstSpeakerConfigurationHolder& vstConfig) { return operator=(vstConfig.get()); } + VstSpeakerConfigurationHolder& operator= (const VstSpeakerConfiguration& vstConfig) + { + VstSpeakerConfiguration& dst = *allocate (vstConfig.numberOfChannels); + + dst.type = vstConfig.type; + dst.numberOfChannels = vstConfig.numberOfChannels; + + for (int i = 0; i < dst.numberOfChannels; ++i) + dst.speakers[i] = vstConfig.speakers[i]; + + return *this; + } + + VstSpeakerConfigurationHolder& operator= (VstSpeakerConfigurationHolder && vstConfig) + { + storage = static_cast&&> (vstConfig.storage); + vstConfig.clear(); + + return *this; + } + + const VstSpeakerConfiguration& get() const { return *storage.getData(); } + + private: + JUCE_LEAK_DETECTOR (VstSpeakerConfigurationHolder) + + HeapBlock storage; + + VstSpeakerConfiguration* allocate (int numChannels) + { + auto arrangementSize = (sizeof (VstSpeakerConfiguration) - sizeof(VstSpeakerConfiguration::speakers)) + + (sizeof (VstIndividualSpeakerInfo) * static_cast (numChannels)); + + storage.malloc (1, arrangementSize); + return storage.getData(); + } + + void clear() + { + VstSpeakerConfiguration& dst = *allocate (0); + + dst.type = vstSpeakerConfigTypeEmpty; + dst.numberOfChannels = 0; + } + }; static const Mapping* getMappings() noexcept { diff --git a/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp b/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp index 9de1aa7a90..1ddc8cec65 100644 --- a/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp +++ b/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp @@ -845,12 +845,10 @@ public: { setRateAndBufferSizeDetails (rate, samplesPerBlockExpected); - VstSpeakerConfiguration inArr, outArr; + SpeakerMappings::VstSpeakerConfigurationHolder inArr (getChannelLayoutOfBus (true, 0)); + SpeakerMappings::VstSpeakerConfigurationHolder outArr (getChannelLayoutOfBus (false, 0)); - SpeakerMappings::channelSetToVstArrangement (getChannelLayoutOfBus (true, 0), inArr); - SpeakerMappings::channelSetToVstArrangement (getChannelLayoutOfBus (false, 0), outArr); - - dispatch (plugInOpcodeSetSpeakerConfiguration, 0, reinterpret_cast (&inArr), &outArr, 0.0f); + dispatch (plugInOpcodeSetSpeakerConfiguration, 0, (pointer_sized_int) &inArr.get(), (void*) &outArr.get(), 0.0f); vstHostTime.tempoBPM = 120.0; vstHostTime.timeSignatureNumerator = 4;