Open jamshark70 opened 5 years ago
hi! i did some debugging and found a few problems related to this.
First, the sendMsg
is not setting the type of the argument to char, it sets the type to the char itself, so when you send an OSC message with $s
as argument, it actually sets the type as that char so the OSC message goes with type ,s
but there is no string there in the content of the message.
The next problem occurs when parsing messages on the receive side. the OSC parser doesn't check if there is a string there before trying to read it, which means that in the case above it tries to parse a string where there is no data, causing the segfault. this would happen with any message received that is not formatted correctly and is a potential security flaw.
A message with tags ,is
but with size 8 (only containing the integer) would also cause a segfault. I think the language should check before trying to parse the OSC message arguments like that. And also set the type as c
for chars. There is even a comment from 2009 here: https://github.com/supercollider/supercollider/blob/develop/lang/LangPrimSource/OSCData.cpp#L644, specifying the default rule: if no tag is matched, consider it a char. But this is also inconsistent with the way we treat chars above on line https://github.com/supercollider/supercollider/blob/develop/lang/LangPrimSource/OSCData.cpp#L621
I plan to open two different PRs to deal with both issues, unless someone points something different with it :)
I think both could be fixed in one PR.
First, the sendMsg is not setting the type of the argument to char, it sets the type to the char itself...
Seems this was done for some reason, but the reason is not stated. Looks like a hack for something though. Doesn't it basically guarantee a malformed message? If the char is a valid type tag, then you have a type tag without data; otherwise we've added an invalid type tag. I have no idea what we were thinking back then.
https://github.com/supercollider/supercollider/commit/b4cb42146acf7ee4c28f4845b9d1fb73bad49728
I remembered later: we use $[ and $] to delimit array arguments in scsynth messages.
x = Synth.basicNew(\default).newMsg(args: [freq: [100, 200, 300]]);
x.asCompileString;
-> [ 9, 'default', 1001, 0, 1, 'freq', $[, 100, 200, 300, $] ]
But sclang's asRawOSC
doesn't handle it correctly (you get #bundle
and one int only):
y = x.asRawOSC;
-> Int8Array[ 35, 98, 117, 110, 100, 108, 101, 0, 0, 0, 0, 9, 0, 0, 0, 0 ]
So it's definitely a messy implementation. If we're going to use chars as this sort of delimiter, probably better to put a true char in the message instead of abusing type tags (why? to save a few bytes?). But then scsynth will also need to be changed to handle the updated format -- and this has the potential to break non-sclang clients.
Or, allow the type tag hack, but only for square brackets -- all other characters should be inserted as true chars.
It is correct that for the beginning of an array, $[
, is added to the type tags. But I suppose that it needs to be added to the message as well.
http://opensoundcontrol.org/spec-1_0 (additional, nonstandard argument types).
Note that there are two longstanding issues in the implementation of the OSC reciever with regards to these nonstandard types as well:
As I read the spec, it looks like we shouldn't need to add any data for $[ and $] -- just the tags.
So the problem then is that we are treating all characters as the same special case.
I tried a few tests against Pure Data. I couldn't test whether our messages with $[ and $] are well formed because PD doesn't support those type tags. But I could confirm that we are sending malformed messages if the character happens to be a valid type tag that expects an argument to be added as well.
PD: [netreceive -u -b 9696] --> [oscparse] --> [print]
n = NetAddr("127.0.0.1", 9696);
// bracket tags: PD says "hello 1 2"
n.sendMsg("/hello", $[, 1, 2, $]);
// unknown tag silently dropped in PD: "hello 3"
n.sendMsg("/hello", $8, 3);
// valid tag without data: "oscparse: OSC message ended prematurely"
n.sendMsg("/hello", $s, 3);
At the very least, sending malformed messages should be preventable.
Environment
Steps to reproduce
Hat tip Fredrik Olofsson.
gdb says (it's a rather long stack full of a lot of boost::asio functions -- I'll leave those out because I'm pretty sure the only relevant part is after it comes into sclang at
SC_UdpInPort::handleReceivedUDP
):Expected vs. actual behavior
It's perhaps too obvious to mention, but the expected behavior would be that sclang receives the character
s
without error.