bug 661036 - websockets allowed prohibited space character in protocol header, with test update r=biesi r=bsmith
authorPatrick McManus <mcmanus@ducksong.com>
Thu, 16 Jun 2011 14:27:11 -0400
changeset 71493 53418bef40e95424118aa854fcfb410a466ef32e
parent 71492 8d78db26d22b081525e4df80059353e57688eef4
child 71494 bdab292ad9cb0fc88e95464ca093a30873d71170
push idunknown
push userunknown
push dateunknown
reviewersbiesi, bsmith
bugs661036
milestone7.0a1
bug 661036 - websockets allowed prohibited space character in protocol header, with test update r=biesi r=bsmith
content/base/src/nsWebSocket.cpp
content/base/test/file_websocket_wsh.py
content/base/test/test_websocket.html
--- a/content/base/src/nsWebSocket.cpp
+++ b/content/base/src/nsWebSocket.cpp
@@ -1060,17 +1060,17 @@ nsWebSocket::SetProtocol(const nsString&
 {
   if (aProtocol.IsEmpty()) {
     return NS_ERROR_DOM_SYNTAX_ERR;
   }
 
   PRUint32 length = aProtocol.Length();
   PRUint32 i;
   for (i = 0; i < length; ++i) {
-    if (aProtocol[i] < static_cast<PRUnichar>(0x0020) ||
+    if (aProtocol[i] < static_cast<PRUnichar>(0x0021) ||
         aProtocol[i] > static_cast<PRUnichar>(0x007E)) {
       return NS_ERROR_DOM_SYNTAX_ERR;
     }
   }
 
   CopyUTF16toUTF8(aProtocol, mProtocol);
   return NS_OK;
 }
--- a/content/base/test/file_websocket_wsh.py
+++ b/content/base/test/file_websocket_wsh.py
@@ -4,94 +4,94 @@ import time
 import sys
 
 # see the list of tests in test_websocket.html
 
 def web_socket_do_extra_handshake(request):
   # must set request.ws_protocol to the selected version from ws_requested_protocols
   request.ws_protocol = request.ws_requested_protocols[0]
 
-  if request.ws_protocol == "test 2.1":
+  if request.ws_protocol == "test-2.1":
     time.sleep(5)
     pass
-  elif request.ws_protocol == "test 9":
+  elif request.ws_protocol == "test-9":
     time.sleep(5)
     pass
-  elif request.ws_protocol == "test 10":
+  elif request.ws_protocol == "test-10":
     time.sleep(5)
     pass
-  elif request.ws_protocol == "test 19":
-    raise ValueError('Aborting (test 19)')
-  elif request.ws_protocol == "test 20" or request.ws_protocol == "test 17":
+  elif request.ws_protocol == "test-19":
+    raise ValueError('Aborting (test-19)')
+  elif request.ws_protocol == "test-20" or request.ws_protocol == "test-17":
     time.sleep(10)
     pass
-  elif request.ws_protocol == "test 22":
+  elif request.ws_protocol == "test-22":
     time.sleep(60)
     pass
   else:
     pass
 
 def web_socket_transfer_data(request):
-  if request.ws_protocol == "test 2.1" or request.ws_protocol == "test 2.2":
+  if request.ws_protocol == "test-2.1" or request.ws_protocol == "test-2.2":
     msgutil.close_connection(request)
-  elif request.ws_protocol == "test 6":
+  elif request.ws_protocol == "test-6":
     resp = "wrong message"
     if msgutil.receive_message(request) == "1":
       resp = "2"
     msgutil.send_message(request, resp.decode('utf-8'))
     resp = "wrong message"
     if msgutil.receive_message(request) == "3":
       resp = "4"
     msgutil.send_message(request, resp.decode('utf-8'))
     resp = "wrong message"
     if msgutil.receive_message(request) == "5":
       resp = "あいうえお"
     msgutil.send_message(request, resp.decode('utf-8'))
     msgutil.close_connection(request)
-  elif request.ws_protocol == "test 7":
+  elif request.ws_protocol == "test-7":
     try:
       while not request.client_terminated:
         msgutil.receive_message(request)
     except msgutil.ConnectionTerminatedException, e:
       pass
     msgutil.send_message(request, "server data")
     msgutil.send_message(request, "server data")
     msgutil.send_message(request, "server data")
     msgutil.send_message(request, "server data")
     msgutil.send_message(request, "server data")
     time.sleep(30)
     msgutil.close_connection(request, True)
-  elif request.ws_protocol == "test 10":
+  elif request.ws_protocol == "test-10":
     msgutil.close_connection(request)
-  elif request.ws_protocol == "test 11":
+  elif request.ws_protocol == "test-11":
     resp = "wrong message"
     if msgutil.receive_message(request) == "client data":
       resp = "server data"
     msgutil.send_message(request, resp.decode('utf-8'))
     msgutil.close_connection(request)
-  elif request.ws_protocol == "test 12":
+  elif request.ws_protocol == "test-12":
     msgutil.close_connection(request)
-  elif request.ws_protocol == "test 13":
+  elif request.ws_protocol == "test-13":
     # first one binary message containing the byte 0x61 ('a')
     request.connection.write('\xff\x01\x61')
     # after a bad utf8 message
     request.connection.write('\x01\x61\xff')
     msgutil.close_connection(request)
-  elif request.ws_protocol == "test 14":
+  elif request.ws_protocol == "test-14":
     msgutil.close_connection(request)
     msgutil.send_message(request, "server data")
-  elif request.ws_protocol == "test 15":
+  elif request.ws_protocol == "test-15":
     msgutil.close_connection(request, True)
     return
-  elif request.ws_protocol == "test 17" or request.ws_protocol == "test 21":
+  elif request.ws_protocol == "test-17" or request.ws_protocol == "test-21":
     time.sleep(5)
     resp = "wrong message"
     if msgutil.receive_message(request) == "client data":
       resp = "server data"
     msgutil.send_message(request, resp.decode('utf-8'))
     time.sleep(5)
     msgutil.close_connection(request)
     time.sleep(5)
-  elif request.ws_protocol == "test 20":
+  elif request.ws_protocol == "test-20":
     msgutil.send_message(request, "server data")
     msgutil.close_connection(request)
   while not request.client_terminated:
     msgutil.receive_message(request)
--- a/content/base/test/test_websocket.html
+++ b/content/base/test/test_websocket.html
@@ -184,32 +184,32 @@ function test1()
   }
   doTest(2);
 }
 
 // this test expects that the serialization list to connect to the proxy
 // is empty
 function test2()
 {
-  var ws1 = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 2.1");
+  var ws1 = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-2.1");
   current_test--; // CreateTestWS incremented this
-  var ws2 = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 2.2");
+  var ws2 = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-2.2");
 
   var ws2CanConnect = false;
 
   // the server will delay ws1 for 5 seconds
 
   ws1.onopen = function()
   {
     ws2CanConnect = true;
   }
 
   ws2.onopen = function()
   {
-    ok(ws2CanConnect, "shouldn't connect yet in test 2!");
+    ok(ws2CanConnect, "shouldn't connect yet in test-2!");
     doTest(3);
   }
 }
 
 function test3()
 {
   var ws = CreateTestWS("ws://this.websocket.server.probably.does.not.exist");
   ws.onopen = shouldNotOpen;
@@ -219,20 +219,20 @@ function test3()
     doTest(4);
   };
 }
 
 function test4()
 {
   try {
     var ws = CreateTestWS("file_websocket");
-    ok(false, "test 4 failed");
+    ok(false, "test-4 failed");
   }
   catch (e) {
-    ok(true, "test 4 failed");
+    ok(true, "test-4 failed");
   }
   doTest(5);
 }
 
 function test5()
 {
   try {
     var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "");
@@ -244,31 +244,39 @@ function test5()
   current_test--; // CreateTestWS incremented this
   try {
     var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "\n");
     ok(false, "couldn't accept any not printable ASCII character in the protocol parameter");
   }
   catch (e) {
     ok(true, "couldn't accept any not printable ASCII character in the protocol parameter");
   }
+  current_test--; // CreateTestWS incremented this
+  try {
+    var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 5");
+    ok(false, "U+0020 not acceptable in protocol parameter");
+  }
+  catch (e) {
+    ok(true, "U+0020 not acceptable in protocol parameter");
+  }
   doTest(6);
 }
 
 function test6()
 {
-  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 6");
+  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-6");
   var counter = 1;
   ws.onopen = function()
   {
     ws.send(counter);
   }
   ws.onmessage = function(e)
   {
     if (counter == 5) {
-      ok(e.data == "あいうえお", "test 6 counter 5 data ok");
+      ok(e.data == "あいうえお", "test-6 counter 5 data ok");
       ws.close();
       doTest(7);
     } else {
       ok(e.data == counter+1, "bad counter");
       counter += 2;
       ws.send(counter);
     }
   }
@@ -281,58 +289,58 @@ function test7()
 // as the server handles the receipt of the close event directly, not
 // as part of the wsh - so we cannot fake the non-clean close which is
 // what we're trying to do here.
 
   ok(true, "test disabled");
   current_test++;
   doTest(8);
 
-//  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 7");
+//  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-7");
 //  ws.onopen = function()
 //  {
 //    ws.close();
 //  }
 //  ws.onclose = function(e)
 //  {
 //    shouldCloseNotCleanly(e);
 //    doTest(8);
 //  };
 }
 
 function test8()
 {
-  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 8");
+  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-8");
   ws.onopen = function()
   {
     ws.close();
   }
   ws.onclose = function(e)
   {
     shouldCloseCleanly(e);
     doTest(9);
   };
 }
 
 function test9()
 {
-  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 9");
+  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-9");
   ws.onopen = shouldNotOpen;
   ws.onclose = function(e)
   {
     shouldCloseNotCleanly(e);
     doTest(10);
   };
 
   ws.close();
 }
 
 function test10()
 {
-  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 10");
+  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-10");
   ws.onclose = shouldCloseCleanly;
 
   try {
     ws.send("client data");
     ok(false, "Couldn't send data before connecting!");
   }
   catch (e) {
     ok(true, "Couldn't send data before connecting!");
@@ -340,117 +348,117 @@ function test10()
   ws.onopen = function()
   {
     doTest(11);
   }
 }
 
 function test11()
 {
-  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 11");
-  ok(ws.readyState == 0, "create bad readyState in test 11!");
+  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-11");
+  ok(ws.readyState == 0, "create bad readyState in test-11!");
   ws.onopen = function()
   {
-    ok(ws.readyState == 1, "open bad readyState in test 11!");
+    ok(ws.readyState == 1, "open bad readyState in test-11!");
     ws.send("client data");
   }
   ws.onmessage = function(e)
   {
-    ok(e.data == "server data", "bad received message in test 11!");
+    ok(e.data == "server data", "bad received message in test-11!");
     ws.close();
 
 // this ok() is disabled due to a race condition - it state may have
 // advanced through 2 (closing) and into 3 (closed) before it is evald
-//    ok(ws.readyState == 2, "onmessage bad readyState in test 11!");
+//    ok(ws.readyState == 2, "onmessage bad readyState in test-11!");
   }
   ws.onclose = function(e)
   {
-    ok(ws.readyState == 3, "onclose bad readyState in test 11!");
+    ok(ws.readyState == 3, "onclose bad readyState in test-11!");
     shouldCloseCleanly(e);
     doTest(12);
   }
 }
 
 function test12()
 {
-  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 12");
+  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-12");
   ws.onopen = function()
   {
     try {
       // send an unpaired surrogate
       ws.send(String.fromCharCode(0xD800));
       ok(false, "couldn't send an unpaired surrogate!");
     }
     catch (e) {
       ok(true, "couldn't send an unpaired surrogate!");
     }
     ws.close();
 
-// there isnt really a server implementation of test 12, so just
+// there isnt really a server implementation of test-12, so just
 // ignore an error
     ws.onerror = function()
     {
     }
 
     doTest(13);
   };
 }
 
 function test13()
 {
     // previous versions of this test counted the number of protocol errors returned, but the 
     // protocol stack typically closes down after reporting a protocol level error - trying
     // to resync is too dangerous
 
-  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 13");
+  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-13");
   ws._timesCalledOnError = 0;
   ws.onerror = function()
   {
     ws._timesCalledOnError++;
   }
   ws.onclose = function(e)
   {
     ok(ws._timesCalledOnError > 0, "no error events");
     doTest(14);
   }
 }
 
 function test14()
 {
-  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 14");
+  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-14");
   ws.onmessage = function()
   {
     ok(false, "shouldn't received message after the server sent the close frame");
   }
   ws.onclose = function(e)
   {
     shouldCloseCleanly(e);
     doTest(15);
   };
 }
 
 function test15()
 {
-  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 15");
+  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-15");
   ws.onclose = function(e)
   {
     shouldCloseNotCleanly(e);
     doTest(16);
   };
 
   // termination of the connection might cause an error event if it happens in OPEN
   ws.onerror = function()
   {
   }
 
 }
 
 function test16()
 {
-  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 16");
+  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-16");
   ws.onopen = function()
   {
     ws.close();
     ok(!ws.send("client data"), "shouldn't send message after calling close()");
     doTest(17);
   }
   ws.onmessage = function()
   {
@@ -464,17 +472,17 @@ function test16()
   {
   }
 }
 
 var status_test17 = "not started";
 
 window._test17 = function()
 {
-  var local_ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 17");
+  var local_ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-17");
   local_ws._testNumber = "local17";
   local_ws._testNumber = current_test++;
 
   status_test17 = "started";
 
   local_ws.onopen = function(e)
   {
     status_test17 = "opened";
@@ -484,24 +492,24 @@ window._test17 = function()
 
   local_ws.onerror = function()
   {
     ok(false, "onerror called on test " + e.target._testNumber + "!");
   };
 
   local_ws.onmessage = function(e)
   {
-    ok(e.data == "server data", "Bad message in test 17");
+    ok(e.data == "server data", "Bad message in test-17");
     status_test17 = "got message";
     forcegc();
   };
 
   local_ws.onclose = function(e)
   {
-    ok(status_test17 == "got message", "Didn't got message in test 17!");
+    ok(status_test17 == "got message", "Didn't got message in test-17!");
     shouldCloseCleanly(e);
     status_test17 = "closed";
     forcegc();
     doTest(18);
     forcegc();
   };
 
   local_ws = null;
@@ -526,28 +534,28 @@ function test18()
   {
     shouldCloseNotCleanly(e);
     doTest(19);
   };
 }
 
 function test19()
 {
-  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 19");
+  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-19");
   ws.onopen = shouldNotOpen;
   ws.onclose = function(e)
   {
     shouldCloseNotCleanly(e);
     doTest(20);
   };
 }
 
 window._test20 = function()
 {
-  var local_ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 20");
+  var local_ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-20");
   local_ws._testNumber = "local20";
   local_ws._testNumber = current_test++;
 
   local_ws.onerror = function()
   {
     ok(false, "onerror called on test " + e.target._testNumber + "!");
   };
 
@@ -566,40 +574,40 @@ function test20()
 {
   window._test20();
 }
 
 var timeoutTest21;
 
 window._test21 = function()
 {
-  var local_ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 21");
+  var local_ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-21");
   local_ws._testNumber = current_test++;
 
   local_ws.onopen = function(e)
   {
     e.target.send("client data");
     timeoutTest21 = setTimeout(function()
     {
-      ok(false, "Didn't received message on test 21!");
+      ok(false, "Didn't received message on test-21!");
     }, 15000);
     forcegc();
     e.target.onopen = null;
     forcegc();
   };
 
   local_ws.onerror = function()
   {
     ok(false, "onerror called on test " + e.target._testNumber + "!");
   };
 
   local_ws.onmessage = function(e)
   {
     clearTimeout(timeoutTest21);
-    ok(e.data == "server data", "Bad message in test 21");
+    ok(e.data == "server data", "Bad message in test-21");
     forcegc();
     e.target.onmessage = null;
     forcegc();
   };
 
   local_ws.onclose = function(e)
   {
     shouldCloseCleanly(e);
@@ -613,17 +621,17 @@ window._test21 = function()
 
 function test21()
 {
   window._test21();
 }
 
 function test22()
 {
-  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 22");
+  var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-22");
   ws.onopen = shouldNotOpen;
   ws.onclose = function(e)
   {
     shouldCloseNotCleanly(e);
     doTest(23);
   };
 }