rabbitmq / rabbitmq-web-stomp

Provides support for STOMP over WebSockets
Other
89 stars 26 forks source link

Crash when receiving arraybuffer data with utf-8 #54

Closed JSteunou closed 8 years ago

JSteunou commented 8 years ago

Hi again ;)

I tried to use the arraybuffer mode. No issue when sending classical data, but I got a crash when sending utf-8 encoded data for chars like ¹ for example. The String version of the frame works fine, but the arraybuffer version is not. Maybe my encoding is wrong, but I feel pretty confident about it because it's quite the same than web-stomp send me back when I'm sending the String version.

string frame (with null byte at the end)

subscription:sub-0
destination:/topic/webstomp-chat-example
message-id:T_sub-0@@session-ogOUJ_VsFoG4yOmDawd9zg@@1
redelivered:false
content-length:31

{"author":"User 1","text":"¹"}

arraybuffer frame

83,69,78,68,10,100,101,115,116,105,110,97,116,105,111,110,58,47,116,111,112,105,99,47,119,101,98,115,116,111,109,112,45,99,104,97,116,45,101,120,97,109,112,108,101,10,99,111,110,116,101,110,116,45,108,101,110,103,116,104,58,51,49,10,10,123,34,97,117,116,104,111,114,34,58,34,85,115,101,114,32,49,34,44,34,116,101,120,116,34,58,34,185,34,125,0

error browser side STOMP died

error rmq log

** {{badmatch,<<"\n">>},
    [{rabbit_stomp_frame,parse_body2,4,
                         [{file,"src/rabbit_stomp_frame.erl"},{line,176}]},
     {rabbit_ws_client,process_received_bytes,3,
                       [{file,"src/rabbit_ws_client.erl"},{line,183}]},
     {rabbit_ws_client,handle_cast,2,
                       [{file,"src/rabbit_ws_client.erl"},{line,93}]},
     {gen_server,try_dispatch,4,[{file,"gen_server.erl"},{line,615}]},
     {gen_server,handle_msg,5,[{file,"gen_server.erl"},{line,681}]},
     {proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,239}]}]}

=ERROR REPORT==== 28-Mar-2016::11:40:08 ===
** Generic server <0.2560.2> terminating 
** Last message in was {'$gen_cast',{sockjs_msg,<<"\n">>}}
** When Server state == {state,
                         {rabbit_ws_handler,<0.2558.2>,
                          [{socket,#Port<0.26449>},
                           {peername,{{127,0,0,1},37344}},
                           {sockname,{{127,0,0,1},15674}}]},
                         {proc_state,"session-raulStfo6cQ0hzWICfMydw",
                          <0.2569.2>,<0.2563.2>,
                          {dict,1,16,16,8,80,48,
                           {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
                           {{[],[],[],[],[],[],[],[],[],[],[],
                             [[<<"T_sub-0">>|
                               {subscription,"/topic/webstomp-chat-example",
                                auto,false,"id='sub-0'"}]],
                             [],[],[],[]}}},
                          "1.1",#Fun<rabbit_ws_client.2.105981754>,undefined,
                          {stomp_configuration,undefined,undefined,false,
                           undefined},
                          {set,0,16,16,8,80,48,
                           {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
                           {{[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],
                             []}}},
                          {dict,0,16,16,8,80,48,
                           {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
                           {{[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],
                             []}}},
                          #Fun<rabbit_stomp_processor.5.57715950>,
                          {amqp_adapter_info,
                           {127,0,0,1},
                           15674,
                           {127,0,0,1},
                           37344,<<"127.0.0.1:37344 -> 127.0.0.1:15674">>,
                           {'Web STOMP',0},
                           [{ssl,false}]},
                          #Fun<rabbit_ws_client.0.105981754>,
                          #Fun<rabbit_ws_client.1.105981754>,none,
                          {127,0,0,1},
                          true},
                         {resume,#Fun<rabbit_stomp_frame.4.116712418>}}
** Reason for termination == 
** {{badmatch,<<"\n">>},
    [{rabbit_stomp_frame,parse_body2,4,
                         [{file,"src/rabbit_stomp_frame.erl"},{line,176}]},
     {rabbit_ws_client,process_received_bytes,3,
                       [{file,"src/rabbit_ws_client.erl"},{line,183}]},
     {rabbit_ws_client,handle_cast,2,
                       [{file,"src/rabbit_ws_client.erl"},{line,93}]},
     {gen_server,try_dispatch,4,[{file,"gen_server.erl"},{line,615}]},
     {gen_server,handle_msg,5,[{file,"gen_server.erl"},{line,681}]},
     {proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,239}]}]}

/etc/rabbitmq/rabbitmq.config

[
  {rabbitmq_web_stomp, [{ws_frame, binary}]}
].

to sum it up: no issue when sending data in a String or ArrayBuffer frame when the body do not contain utf-8 encoded char. But when it is present, it crashes only in ArrayBuffer mode.

michaelklishin commented 8 years ago

Array buffer sounds like a JavaScript data structure. Can you post your code, please?

JSteunou commented 8 years ago
function unicodeStringToTypedArray(s) {
    let escstr = encodeURIComponent(s);
    let binstr = escstr.replace(/%([0-9A-F]{2})/g, (match, p1) => String.fromCharCode('0x' + p1));
    let arr = Array.prototype.map.call(s, (c) => c.charCodeAt(0));
    return new Uint8Array(arr);
}

I'm using this to convert String frame created by stomp.js plugin.

essen commented 8 years ago

We have exactly the same code for handling text vs binary frames (array i believe sends a binary). The only difference is the lack of utf-8 check on binary. If I had to guess I would think the error is in your code. Can you convert your array back to a string?

JSteunou commented 8 years ago
var arr = [83,69,78,68,10,100,101,115,116,105,110,97,116,105,111,110,58,47,116,111,112,105,99,47,119,101,98,115,116,111,109,112,45,99,104,97,116,45,101,120,97,109,112,108,101,10,99,111,110,116,101,110,116,45,108,101,110,103,116,104,58,51,49,10,10,123,34,97,117,116,104,111,114,34,58,34,85,115,101,114,32,49,34,44,34,116,101,120,116,34,58,34,185,34,125,0];
var binstr = String.fromCharCode(...new Uint8Array(arr));

binstr
"SEND
destination:/topic/webstomp-chat-example
content-length:31

{"author":"User 1","text":"¹"}

and last char is null byte

JSteunou commented 8 years ago

I can invite you on my gitlab project if it helps @essen

essen commented 8 years ago

Well 185 isn't a valid UTF-8 value so the error is definitely in the encoding. :-)

JSteunou commented 8 years ago

I see. I must have the same error twice in decode and in encode function Le 28 mars 2016 1:11 PM, "Loïc Hoguin" notifications@github.com a écrit :

Well 185 isn't a valid UTF-8 value so the error is definitely in the encoding. :-)

— You are receiving this because you authored the thread. Reply to this email directly or view it on GitHub https://github.com/rabbitmq/rabbitmq-web-stomp/issues/54#issuecomment-202343428

JSteunou commented 8 years ago

Pfff find it, silly bug in my encode function. I built my array with the original string, not the escaped one. And even if it's not valid as an utf-8 value, browser can still decode it so I did not see any error in the decode process. See

String.fromCharCode(185)
"¹"

oO

Thank you for pointing me in the right direction @essen!