Skip to content

Commit d5a115d

Browse files
committed
Strip - fixed crash when removing modules added by STRIP in plugin-version of Rack
1 parent 1505360 commit d5a115d

4 files changed

Lines changed: 38 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
- Fixed saving of SysEx data logging setting
1919
- Module [PANIC ROOM](./docs/panicroom/PanicRoom.md)
2020
- Added options to limit the number of allowed modules and cables
21+
- Module [STRIP](./docs/strip/Strip.md)
22+
- Fixed crash when removing modules added by STRIP in plugin-version of Rack
2123
- Module [TRANSIT](./docs/transit/Transit.md)
2224
- Fade CV input is now additive to per-slot fade time (previously CV was only additive to the global _FADE_ knob)
2325
- Added Output-mode "Tipsy" for sending the snapshot text label (for modules with Tipsy-support like [TTY](https://library.vcvrack.com/StochasticTelegraph/TTY))

docs/strip/Strip.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,6 @@ STRIP-BAY is a companion module for STRIP: It is used to name some "patching-poi
105105
- v2.2.0
106106
- Remember and recall file-dialog folder locations for vcvss and vcvs files
107107
- v2.3.1
108-
- Fixed changed behavior on excluded/included parameters for randomization introduced in v2.3.0
108+
- Fixed changed behavior on excluded/included parameters for randomization introduced in v2.3.0
109+
- v2.5.0
110+
- Fixed crash when removing modules added by STRIP in plugin-version of Rack

src/modules/strip/Strip.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22
#include "../../plugin.hpp"
33
#include "../../utils/StripIdFixModule.hpp"
4+
#include "../../utils/vcv_files.hpp"
45
#include <osdialog.h>
56
#include <plugin.hpp>
67

@@ -679,6 +680,9 @@ struct StripWidgetBase : ThemedModuleWidget<MODULE> {
679680
StripIdFixModule* m = dynamic_cast<StripIdFixModule*>(mw->module);
680681
if (m) m->idFixDataFromJson(modules);
681682

683+
// Drop engine-runtime binding fields, like Rack's own preset loader.
684+
vcv::jsonStripIds(moduleJ);
685+
682686
mw->fromJson(moduleJ);
683687

684688
h->newModuleJ = mw->toJson();
@@ -706,6 +710,9 @@ struct StripWidgetBase : ThemedModuleWidget<MODULE> {
706710
StripIdFixModule* m = dynamic_cast<StripIdFixModule*>(mw->module);
707711
if (m) m->idFixDataFromJson(modules);
708712

713+
// Drop engine-runtime binding fields, like Rack's own preset loader.
714+
vcv::jsonStripIds(moduleJ);
715+
709716
mw->fromJson(moduleJ);
710717

711718
h->newModuleJ = mw->toJson();
@@ -738,6 +745,9 @@ struct StripWidgetBase : ThemedModuleWidget<MODULE> {
738745
StripIdFixModule* m = dynamic_cast<StripIdFixModule*>(mw->module);
739746
if (m) m->idFixDataFromJson(modules);
740747

748+
// Drop engine-runtime binding fields, like Rack's own preset loader.
749+
vcv::jsonStripIds(moduleJ);
750+
741751
mw->fromJson(moduleJ);
742752

743753
h->newModuleJ = mw->toJson();

src/utils/vcv_files.hpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,26 @@ namespace vcv {
99

1010
static const char SELECTION_FILTERS[] = "VCV Rack module selection (.vcvs):vcvs";
1111

12+
/**
13+
* Removes engine-runtime binding fields from a module's JSON before it is applied
14+
* to an already-created module with ModuleWidget::fromJson(). Mirrors Rack's own
15+
* engine::Module::jsonStripIds(), which every Rack preset/clipboard load calls
16+
* before fromJson(). Restoring these fields would transplant another instance's
17+
* bindings onto the new module; in particular a stale "automId" desyncs the module
18+
* from the engine's host-automation map (automModuleMap) and causes a use-after-free
19+
* in getAutomParamQuantity() on the next module removal.
20+
* NB: unlike Rack's version, "id" is intentionally kept - callers read it for id
21+
* remapping (StripIdFixModule) and rely on it.
22+
*/
23+
#if defined(__GNUC__) || defined(__clang__)
24+
__attribute__((unused))
25+
#endif
26+
static void jsonStripIds(json_t* moduleJ) {
27+
json_object_del(moduleJ, "leftModuleId");
28+
json_object_del(moduleJ, "rightModuleId");
29+
json_object_del(moduleJ, "automId");
30+
}
31+
1232
/**
1333
* Creates a module from JSON data, also returns the previous id of the module.
1434
* @param moduleJ JSON representation of the module
@@ -282,6 +302,9 @@ static std::vector<history::Action*>* vcvsFromJson_presets(json_t* rootJ, std::m
282302
StripIdFixModule* m = dynamic_cast<StripIdFixModule*>(mw->module);
283303
if (m) m->idFixDataFromJson(modules);
284304

305+
// Drop engine-runtime binding fields, like Rack's own preset loader.
306+
jsonStripIds(moduleJ);
307+
285308
mw->fromJson(moduleJ);
286309

287310
h->newModuleJ = mw->toJson();

0 commit comments

Comments
 (0)