Rack crashes when loading a wrong preset in a module

Oh I see… in this case the module developers are the same people as the VCV Rack developers! Good catch! So reporting to support@vcvrack.com was already the best option.

1 Like

Good idea, maybe @rsmus7 or @pgatt can split this into a new topic ?

done

2 Likes

This whole topic has got me thinking as a plugin developer. When processing JSON, I will keep two rules in mind from now on:

  1. Always be paranoid when parsing a JSON data structure. Don’t assume anything. (I think my code already does this.)
  2. In addition, I will consider having some kind of distinctive signature in the JSON and immediately ignore the whole thing if it’s missing or wrong. Something like {"signature": "MyModuleNameHere", ...}.

Since I use JSON for Meander parameter and custom harmonic progressions data, I should know this but do not. Do the dataToJson() and dataFromJson functions segregate JSON data from multiple modules? Or, is the data common to the patch? I.E., if someone else uses the same text tags in their module, could we step on each other? Is this what you are wanting to prevent as you mention above?

Yeah, I realize now I should have done an experiment before I wrote that. The pair of functions you mention only handle part of the entire JSON blob, and the entire JSON blob is what is in the preset. For example, if I save a preset file (vcvm extension) from my Moots module, it ends up with the following JSON content:

{
  "plugin": "CosineKitty-Sapphire",
  "model": "Moots",
  "version": "2.1.3",
  "params": [
    {
      "value": 0.0,
      "id": 0
    },
    {
      "value": 0.0,
      "id": 1
    },
    {
      "value": 0.0,
      "id": 2
    },
    {
      "value": 0.0,
      "id": 3
    },
    {
      "value": 0.0,
      "id": 4
    }
  ],
  "data": {
    "slew": [
      true,
      true,
      false,
      false,
      false
    ]
  }
}

The "data" part is the only part that the pair of functions you mention, dataToJson and dataFromJson, has any access to. It’s like VCV Rack puts that in a little sandbox for that pair of functions, and it handles all the rest of the JSON representation of your module’s state.

So while I could put a signature in my data object, I don’t think that’s really a good solution, because it’s possible a crash could happen outside our control if VCV Rack has loaded the JSON representation for an alien module. It needs more research for sure.

1 Like

Isn’t the crash in rack itself? It looks to me like it’s in history.cpp:


ModuleChange::~ModuleChange() {
	json_decref(oldModuleJ);
	json_decref(newModuleJ);
}

That said, I not great at decoding crash logs…

Yes, you are right. I was already in the process of confirming I could crash VCV Rack by loading a preset for the wrong module on purpose. I saved a preset for Sapphire Elastika, then tried to load it in Sapphire Moots, and boom:

[692.291 fatal adapters/standalone.cpp:49 fatalSignalHandler] Fatal signal 11. Stack trace:
14: /home/don/Rack/2.2.1_donpatch/Rack() [0x40484b]
13: /lib/x86_64-linux-gnu/libc.so.6(+0x38d60)
12: ./libRack.so(rack::history::ModuleChange::~ModuleChange()+0x36)
11: ./libRack.so(rack::history::ModuleChange::~ModuleChange()+0x11)
10: ./libRack.so(+0x2af6b2)
9: ./libRack.so(rack::app::ModuleWidget::loadDialog()+0xb1)
8: ./libRack.so(rack::createMenuItem<rack::ui::MenuItem>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic
7: ./libRack.so(rack::ui::MenuItem::doAction(bool)+0x5b)
6: ./libRack.so(rack::widget::EventState::handleButton(rack::math::Vec, int, int, int)+0x31b)
5: ./libRack.so(_glfwPollEventsX11+0x1082)
4: ./libRack.so(rack::window::Window::step()+0x7c)
3: ./libRack.so(rack::window::Window::run()+0x28)
2: /home/don/Rack/2.2.1_donpatch/Rack(main+0xc51)
1: /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xea)
0: /home/don/Rack/2.2.1_donpatch/Rack() [0x40476a]

Do you examine the JSON data in the autosave patch file since the actual patch vcv file is not a simple text file?

I have done that before. It is a zstd-encoded blob that contains a mixture of JSON and some other binary gunk. It is possible to see the JSON by using the zstd command line utility (I had to go find the package and install it on my Debian system). For example:

don@doctorno:~/.Rack2/patches$ cat weird.vcv | unzstd 
./000755 000000 000000 00000000000 14311701423 007355 5ustar00000000 000000 ./modules/000755 000000 000000 00000000000 14311701167 011032 5ustar00000000 000000 ./patch.json000644 000000 000000 00000012574 14311701423 011360 0ustar00000000 000000 {
  "version": "2.0.6",
  "path": "/home/don/.Rack2/patches/weird.vcv",
  "zoom": 1.6817927360534668,
  "gridOffset": [
    -4.3695311546325684,
    -0.37568873167037964
  ],
  "modules": [
    {
      "id": 6514634019236976,
      "plugin": "Fundamental",
      "model": "VCO",
      "version": "2.3.1",
      "params": [
        {
          "value": 0.0,
          "id": 0
        },
        {
          "value": 1.0,
          "id": 1
        },
        {
          "value": -54.0,
          "id": 2
        },
...
1 Like

Oh wait, maybe you are talking about something else. I didn’t look at autosave, just the decompressed vcv as mentioned above, and the vcvm file you get from saving a preset for a module.

Oh, also, you can see your module’s state by hovering the mouse over it, pressing Ctrl+C, then going into your favorite text editor and pasting from the clipboard. You get the full JSON dump of your module state.

So, looking at the autosave file shows that my JSON data is encapsulated within my plugin and module headers, so the data should be segregated from other modules parsing or writing JSON data to the patch file.

And, there is a section for each Meander instance with different “id” tags.

oh, this stack trace has the un-obfuscated stack, so it’s easy to see it’s rack::history::ModuleChange::~ModuleChange()+0x11. Why is this stack trace nice, and the previous one more “raw”?

Previous: ZN4rack7history12ModuleChangeD0Ev 0x7ffd7b2e3b30

Yes, I see what you mean. The problem isn’t with loading/saving patches, it’s with saving a preset from one module and loading into another:

I saved a preset for Elastika:

Then I loaded it into Moots:

This required me to be intentionally obtuse by navigating into the wrong directory and loading something clearly under a directory called Elastika, into a different module Moots.

And it blowed up real good!!!

1 Like

yeah, for sure not super easy to do, for a real user.

Yes, I was just trying to understand whether the same or similar crash could occur via the vcv patch file JSON data. Thanks.

1 Like

The stack traces look nicer on Linux than on Windows. The Linux stack dumper does a nice job of unmangling the C++ function names.

1 Like

This is a slightly OT question, but is there a way to determine which preset is loaded for a module? I’m probably overlooking the obvious, but I do not see a way. Playing with Vult Opulus.

2 Likes

Yes, I have wondered / wished for the same.

I suppose the information is likely moot once parameters are changed after loading the preset. But sometimes I am curious about the “last loaded preset name”

3 Likes

Thanks. Since there is no way to determine the last preset loaded, I will just add a TD-202 text label module to the left of my Opulus modules and manually keep track of which preset this instance is based upon.