From dc7c98862382451ccdb5f731fd080719ebfd2956 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Mon, 15 Feb 2021 21:08:41 +0100 Subject: [PATCH] Fix segfault in REAPER due to new vendor extension This `effVendorSpecific` call would pass a non-zero non-pointer value to the pointer argument, which would then of course result in segfaults. --- CHANGELOG.md | 6 ++++++ src/common/communication/vst2.cpp | 24 +++++++++++++++--------- src/common/logging/vst2.cpp | 3 +++ src/common/vst24.h | 8 ++++++++ 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b821905d..a7fd2c7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,12 @@ Versioning](https://semver.org/spec/v2.0.0.html). yabridge now includes a small workaround to make sure that the affected code never gets compiled. +### Fixed + +- Added a workaround for **REAPER** using a new vendor-specific VST2.4 extension + that passes a non-pointer value to a pointer parameter. This would cause + segfaults with some plugins. + ## [3.0.0] - 2021-02-14 ### Added diff --git a/src/common/communication/vst2.cpp b/src/common/communication/vst2.cpp index 1fcc0fd6..89d53370 100644 --- a/src/common/communication/vst2.cpp +++ b/src/common/communication/vst2.cpp @@ -16,21 +16,27 @@ #include "vst2.h" -EventPayload DefaultDataConverter::read(const int /*opcode*/, - const int /*index*/, +EventPayload DefaultDataConverter::read(const int opcode, + const int index, const intptr_t /*value*/, const void* data) const { + // HACK: REAPER has recently started using `effVendorSpecific` with a + // non-pointer `data` argument, so we need to explicitly handle this + if (opcode == effVendorSpecific && index == effSetSpeakerArrangement) { + return static_cast(reinterpret_cast(data)); + } + if (!data) { return nullptr; } - // This is a simple fallback that will work in almost every case. - // Because some plugins don't zero out their string buffers when sending - // host callbacks, we will explicitely list all callbacks that expect a - // string in `DispatchDataConverter` adn `HostCallbackDataConverter`. - const char* c_string = static_cast(data); - if (c_string[0] != 0) { - return std::string(c_string); + // This is a simple fallback that will work in almost every case. Because + // some plugins don't zero out their string buffers when sending host + // callbacks, we will explicitely list all callbacks that expect a string in + // `DispatchDataConverter` and `HostCallbackDataConverter`. + const char* str = static_cast(data); + if (str[0] != 0) { + return std::string(str); } else { return WantsString{}; } diff --git a/src/common/logging/vst2.cpp b/src/common/logging/vst2.cpp index 1646f549..9241a1ae 100644 --- a/src/common/logging/vst2.cpp +++ b/src/common/logging/vst2.cpp @@ -156,6 +156,9 @@ std::optional opcode_to_string(bool is_dispatch, int opcode) { case effGetSpeakerArrangement: return "effGetSpeakerArrangement"; break; + case effVendorSpecific: + return "effVendorSpecific"; + break; case effGetTailSize: return "effGetTailSize"; break; diff --git a/src/common/vst24.h b/src/common/vst24.h index 8d9b0da3..a17f86f8 100644 --- a/src/common/vst24.h +++ b/src/common/vst24.h @@ -47,6 +47,14 @@ [[maybe_unused]] constexpr int effSetSpeakerArrangement = 42; [[maybe_unused]] constexpr int effGetSpeakerArrangement = 69; +/** + * Used by REAPER for some VST2.4 extensions. Most of the arguments passed to + * this will be able to be handled automatically by our `DefaultDataConverter`. + * We need one special case because for when they're now using the `data` + * argument with a non-pointer value. Found on the same list as above. + */ +[[maybe_unused]] constexpr int effVendorSpecific = 50; + /** * Used by hosts to query the length of reverb tails (equivalent to * `IAudioProcessor::getTailSamples`). Found on the same list as above.