[SCM] WebKit Debian packaging branch, webkit-1.3, updated. upstream/1.3.7-4207-g178b198

commit-queue at webkit.org commit-queue at webkit.org
Sun Feb 20 22:45:32 UTC 2011


The following commit has been merged in the webkit-1.3 branch:
commit d9cfa0f056d7fd06f3e12c5dd84a2b5b28493a0c
Author: commit-queue at webkit.org <commit-queue at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Tue Jan 11 02:26:06 2011 +0000

    2011-01-10  Joe Mason  <jmason at rim.com>
    
            Reviewed by Alexey Proskuryakov.
    
            WebSockets: unbounded buffer growth when server sends bad data
            https://bugs.webkit.org/show_bug.cgi?id=51253
    
            Tests that a websocket handshake should fail after 1024 bytes without a
            newline, or if it contains a null byte before the first newline.
    
            * http/tests/websocket/tests/handshake-fail-by-maxlength-expected.txt: Added.
            * http/tests/websocket/tests/handshake-fail-by-maxlength.html: Added.
            * http/tests/websocket/tests/handshake-fail-by-maxlength_wsh.py: Added.
            * http/tests/websocket/tests/handshake-fail-by-prepended-null-expected.txt: Added.
            * http/tests/websocket/tests/handshake-fail-by-prepended-null.html: Added.
            * http/tests/websocket/tests/handshake-fail-by-prepended-null_wsh.py: Added.
    2011-01-10  Joe Mason  <jmason at rim.com>
    
            Reviewed by Alexey Proskuryakov.
    
            WebSockets: unbounded buffer growth when server sends bad data
            https://bugs.webkit.org/show_bug.cgi?id=51253
    
            Fail a websocket handshake after 1024 bytes without a newline, or if it
            contains a null byte before the first newline.
    
            Tests: http/tests/websocket/tests/handshake-fail-by-maxlength.html
                   http/tests/websocket/tests/handshake-fail-by-prepended-null.html
    
            * websockets/WebSocketHandshake.cpp:
            (WebCore::WebSocketHandshake::readStatusLine):
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@75461 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 039789a..7820fe2 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,20 @@
+2011-01-10  Joe Mason  <jmason at rim.com>
+
+        Reviewed by Alexey Proskuryakov.
+
+        WebSockets: unbounded buffer growth when server sends bad data
+        https://bugs.webkit.org/show_bug.cgi?id=51253
+
+        Tests that a websocket handshake should fail after 1024 bytes without a
+        newline, or if it contains a null byte before the first newline.
+        
+        * http/tests/websocket/tests/handshake-fail-by-maxlength-expected.txt: Added.
+        * http/tests/websocket/tests/handshake-fail-by-maxlength.html: Added.
+        * http/tests/websocket/tests/handshake-fail-by-maxlength_wsh.py: Added.
+        * http/tests/websocket/tests/handshake-fail-by-prepended-null-expected.txt: Added.
+        * http/tests/websocket/tests/handshake-fail-by-prepended-null.html: Added.
+        * http/tests/websocket/tests/handshake-fail-by-prepended-null_wsh.py: Added.
+
 2011-01-10  Jer Noble  <jer.noble at apple.com>
 
         Reviewed by Simon Fraser.
diff --git a/LayoutTests/http/tests/websocket/tests/handshake-fail-by-maxlength-expected.txt b/LayoutTests/http/tests/websocket/tests/handshake-fail-by-maxlength-expected.txt
new file mode 100644
index 0000000..61ee73b
--- /dev/null
+++ b/LayoutTests/http/tests/websocket/tests/handshake-fail-by-maxlength-expected.txt
@@ -0,0 +1,12 @@
+CONSOLE MESSAGE: line 0: Status line is too long
+Connection should fail immediately, rather than succeeding or staying in limbo until timeout, if handshake is longer than 1024 bytes.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+PASS timedOut is false
+PASS connected is false
+PASS origin is undefined.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/websocket/tests/handshake-fail-by-maxlength.html b/LayoutTests/http/tests/websocket/tests/handshake-fail-by-maxlength.html
new file mode 100644
index 0000000..66cbfd0
--- /dev/null
+++ b/LayoutTests/http/tests/websocket/tests/handshake-fail-by-maxlength.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../../../js-test-resources/js-test-style.css">
+<script src="../../../js-test-resources/js-test-pre.js"></script>
+<script src="../../../js-test-resources/js-test-post-function.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+description('Connection should fail immediately, rather than succeeding or staying in limbo until timeout, if handshake is longer than 1024 bytes.');
+
+if (window.layoutTestController)
+    layoutTestController.waitUntilDone()
+
+var timedOut = false;
+var connected = false;
+var origin;
+
+function endTest() {
+    shouldBeFalse('timedOut');
+    shouldBeFalse('connected');
+    shouldBeUndefined('origin');
+    clearTimeout(timeoutID);
+    isSuccessfullyParsed();
+    if (window.layoutTestController)
+        layoutTestController.notifyDone();
+}
+
+var url = 'ws://localhost:8880/websocket/tests/handshake-fail-by-maxlength';
+var ws = new WebSocket(url);
+
+ws.onopen = function()
+{
+    debug('Connected');
+    connected = true;
+}
+
+ws.onmessage = function(messageEvent)
+{
+    origin = messageEvent.data;
+    debug('origin = ' + origin);
+    ws.close();
+}
+
+ws.onclose = function()
+{
+    endTest();
+}
+
+function timeoutCallback()
+{
+    debug('Timed out (state = ' + ws.readyState + ')');
+    timedOut = true;
+    endTest();
+}
+
+var timeoutID = setTimeout(timeoutCallback, 3000);
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/websocket/tests/handshake-fail-by-maxlength_wsh.py b/LayoutTests/http/tests/websocket/tests/handshake-fail-by-maxlength_wsh.py
new file mode 100644
index 0000000..fc7ffb5
--- /dev/null
+++ b/LayoutTests/http/tests/websocket/tests/handshake-fail-by-maxlength_wsh.py
@@ -0,0 +1,44 @@
+# Copyright (C) Research In Motion Limited 2011. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+# following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+# disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
+# following disclaimer in the documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS “AS IS” AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+# APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import time
+
+def web_socket_do_extra_handshake(request):
+    # This will cause the handshake to fail because it pushes the length of the
+    # status line past 1024 characters
+    msg = ""
+    for i in range(0, 1024):
+        msg += "."
+    msg += 'HTTP/1.1 101 WebSocket Protocol Handshake\r\n'
+    msg += 'Upgrade: WebSocket\r\n'
+    msg += 'Connection: Upgrade\r\n'
+    msg += 'Sec-WebSocket-Location: ' + request.ws_location + '\r\n'
+    msg += 'Sec-WebSocket-Origin: ' + request.ws_origin + '\r\n'
+    msg += '\r\n'
+    msg += request.ws_challenge_md5
+    request.connection.write(msg)
+    # continue writing data until the client disconnects
+    while True:
+        time.sleep(1)
+        request.connection.write('keepalive\n')
+
+def web_socket_transfer_data(request):
+    pass
diff --git a/LayoutTests/http/tests/websocket/tests/handshake-fail-by-prepended-null-expected.txt b/LayoutTests/http/tests/websocket/tests/handshake-fail-by-prepended-null-expected.txt
new file mode 100644
index 0000000..5db17c8
--- /dev/null
+++ b/LayoutTests/http/tests/websocket/tests/handshake-fail-by-prepended-null-expected.txt
@@ -0,0 +1,12 @@
+CONSOLE MESSAGE: line 0: Status line contains embedded null
+Connection should fail immediately, rather than succeeding or staying in limbo until timeout, if a null byte is received before the handshake.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+PASS timedOut is false
+PASS connected is false
+PASS origin is undefined.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/websocket/tests/handshake-fail-by-prepended-null.html b/LayoutTests/http/tests/websocket/tests/handshake-fail-by-prepended-null.html
new file mode 100644
index 0000000..f728ede
--- /dev/null
+++ b/LayoutTests/http/tests/websocket/tests/handshake-fail-by-prepended-null.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../../../js-test-resources/js-test-style.css">
+<script src="../../../js-test-resources/js-test-pre.js"></script>
+<script src="../../../js-test-resources/js-test-post-function.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+description('Connection should fail immediately, rather than succeeding or staying in limbo until timeout, if a null byte is received before the handshake.');
+
+if (window.layoutTestController)
+    layoutTestController.waitUntilDone()
+
+var timedOut = false;
+var connected = false;
+var origin;
+
+function endTest() {
+    shouldBeFalse('timedOut');
+    shouldBeFalse('connected');
+    shouldBeUndefined('origin');
+    clearTimeout(timeoutID);
+    isSuccessfullyParsed();
+    if (window.layoutTestController)
+        layoutTestController.notifyDone();
+}
+
+var url = 'ws://localhost:8880/websocket/tests/handshake-fail-by-prepended-null';
+var ws = new WebSocket(url);
+
+ws.onopen = function()
+{
+    debug('Connected');
+    connected = true;
+}
+
+ws.onmessage = function(messageEvent)
+{
+    origin = messageEvent.data;
+    debug('origin = ' + origin);
+    ws.close();
+}
+
+ws.onclose = function()
+{
+    endTest();
+}
+
+function timeoutCallback()
+{
+    debug('Timed out (state = ' + ws.readyState + ')');
+    timedOut = true;
+    endTest();
+}
+
+var timeoutID = setTimeout(timeoutCallback, 3000);
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/websocket/tests/handshake-fail-by-prepended-null_wsh.py b/LayoutTests/http/tests/websocket/tests/handshake-fail-by-prepended-null_wsh.py
new file mode 100644
index 0000000..84c2b97
--- /dev/null
+++ b/LayoutTests/http/tests/websocket/tests/handshake-fail-by-prepended-null_wsh.py
@@ -0,0 +1,49 @@
+# Copyright (C) Research In Motion Limited 2011. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+# following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+# disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
+# following disclaimer in the documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS “AS IS” AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+# APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import time
+
+def web_socket_do_extra_handshake(request):
+    # This simulates a broken server that sends a WebSocket frame before the
+    # handshake, and more frames afterwards.  It is important that if this
+    # happens the client does not buffer all the frames as the server continues
+    # to send more data - it should abort after reading a reasonable number of
+    # bytes (set arbitrarily to 1024).
+    frame = '\0Frame-contains-thirty-two-bytes'
+
+    msg = frame
+    msg += 'HTTP/1.1 101 WebSocket Protocol Handshake\r\n'
+    msg += 'Upgrade: WebSocket\r\n'
+    msg += 'Connection: Upgrade\r\n'
+    msg += 'Sec-WebSocket-Location: ' + request.ws_location + '\r\n'
+    msg += 'Sec-WebSocket-Origin: ' + request.ws_origin + '\r\n'
+    msg += '\r\n'
+    msg += request.ws_challenge_md5
+    request.connection.write(msg)
+    # continue writing data until the client disconnects
+    while True:
+        time.sleep(1)
+        numFrames = 1024 / len(frame) # write over 1024 bytes including the above handshake
+        for i in range(0, numFrames):
+            request.connection.write(frame)
+
+def web_socket_transfer_data(request):
+    pass
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index e450f66..0e9a4f6 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,19 @@
+2011-01-10  Joe Mason  <jmason at rim.com>
+
+        Reviewed by Alexey Proskuryakov.
+
+        WebSockets: unbounded buffer growth when server sends bad data
+        https://bugs.webkit.org/show_bug.cgi?id=51253
+
+        Fail a websocket handshake after 1024 bytes without a newline, or if it
+        contains a null byte before the first newline.
+
+        Tests: http/tests/websocket/tests/handshake-fail-by-maxlength.html
+               http/tests/websocket/tests/handshake-fail-by-prepended-null.html
+
+        * websockets/WebSocketHandshake.cpp:
+        (WebCore::WebSocketHandshake::readStatusLine):
+
 2011-01-10  Adam Barth  <abarth at webkit.org>
 
         Reviewed by Darin Adler.
diff --git a/Source/WebCore/websockets/WebSocketHandshake.cpp b/Source/WebCore/websockets/WebSocketHandshake.cpp
index 5049098..9506ad4 100644
--- a/Source/WebCore/websockets/WebSocketHandshake.cpp
+++ b/Source/WebCore/websockets/WebSocketHandshake.cpp
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2009 Google Inc.  All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -427,6 +428,10 @@ KURL WebSocketHandshake::httpURLForAuthenticationAndCookies() const
 // statusCode and statusText will be set to -1 and a null string, respectively.
 int WebSocketHandshake::readStatusLine(const char* header, size_t headerLength, int& statusCode, String& statusText)
 {
+    // Arbitrary size limit to prevent the server from sending an unbounded
+    // amount of data with no newlines and forcing us to buffer it all.
+    static const int maximumLength = 1024;
+
     statusCode = -1;
     statusText = String();
 
@@ -441,6 +446,12 @@ int WebSocketHandshake::readStatusLine(const char* header, size_t headerLength,
                 space1 = p;
             else if (!space2)
                 space2 = p;
+        } else if (*p == '\0') {
+            // The caller isn't prepared to deal with null bytes in status
+            // line. WebSockets specification doesn't prohibit this, but HTTP
+            // does, so we'll just treat this as an error. 
+            m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "Status line contains embedded null", 0, clientOrigin());
+            return p + 1 - header;
         } else if (*p == '\n')
             break;
     }
@@ -448,9 +459,9 @@ int WebSocketHandshake::readStatusLine(const char* header, size_t headerLength,
         return -1; // We have not received '\n' yet.
 
     const char* end = p + 1;
-    if (end - header > INT_MAX) {
-        m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "Status line is too long: " + trimConsoleMessage(header, maxConsoleMessageSize + 1), 0, clientOrigin());
-        return INT_MAX;
+    if (end - header > maximumLength) {
+        m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "Status line is too long", 0, clientOrigin());
+        return maximumLength;
     }
     int lineLength = end - header;
 

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list