| Differences between
and this patch
- Source/WebCore/ChangeLog +16 lines
Lines 1-3 Source/WebCore/ChangeLog_sec1
1
2011-01-09  Joe Mason  <jmason@rim.com>
2
3
        Reviewed by NOBODY (OOPS!).
4
5
        WebSockets: unbounded buffer growth when server sends bad data
6
        https://bugs.webkit.org/show_bug.cgi?id=51253
7
8
        Fail a websocket handshake after 1024 bytes without a newline, or if it
9
        contains a null byte before the first newline.
10
11
        Tests: http/tests/websocket/tests/handshake-fail-by-maxlength.html
12
               http/tests/websocket/tests/handshake-fail-by-prepended-null.html
13
14
        * websockets/WebSocketHandshake.cpp:
15
        (WebCore::WebSocketHandshake::readStatusLine):
16
1
2011-01-09  Sheriff Bot  <webkit.review.bot@gmail.com>
17
2011-01-09  Sheriff Bot  <webkit.review.bot@gmail.com>
2
18
3
        Unreviewed, rolling out r75337.
19
        Unreviewed, rolling out r75337.
- Source/WebCore/websockets/WebSocketHandshake.cpp -2 / +15 lines
Lines 1-5 Source/WebCore/websockets/WebSocketHandshake.cpp_sec1
1
/*
1
/*
2
 * Copyright (C) 2009 Google Inc.  All rights reserved.
2
 * Copyright (C) 2009 Google Inc.  All rights reserved.
3
 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
3
 *
4
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions are
6
 * modification, are permitted provided that the following conditions are
Lines 427-432 KURL WebSocketHandshake::httpURLForAuthe Source/WebCore/websockets/WebSocketHandshake.cpp_sec2
427
// statusCode and statusText will be set to -1 and a null string, respectively.
428
// statusCode and statusText will be set to -1 and a null string, respectively.
428
int WebSocketHandshake::readStatusLine(const char* header, size_t headerLength, int& statusCode, String& statusText)
429
int WebSocketHandshake::readStatusLine(const char* header, size_t headerLength, int& statusCode, String& statusText)
429
{
430
{
431
    // Arbitrary size limit to prevent the server from sending an unbounded
432
    // amount of data with no newlines and forcing us to buffer it all.
433
    static const size_t maxLength = 1024;
434
430
    statusCode = -1;
435
    statusCode = -1;
431
    statusText = String();
436
    statusText = String();
432
437
Lines 441-446 int WebSocketHandshake::readStatusLine(c Source/WebCore/websockets/WebSocketHandshake.cpp_sec3
441
                space1 = p;
446
                space1 = p;
442
            else if (!space2)
447
            else if (!space2)
443
                space2 = p;
448
                space2 = p;
449
        } else if (*p == '\0') {
450
            // The caller will search for the ending newline with strnstr,
451
            // which does not scan past nulls.  So a null in the stream will
452
            // cause it to loop forever, reading more data and then repeating
453
            // the search only on the data before the null, unless we abort
454
            // immediately.
455
            m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "Status line contains embedded null", 0, clientOrigin());
456
            return p + 1 - header;
444
        } else if (*p == '\n')
457
        } else if (*p == '\n')
445
            break;
458
            break;
446
    }
459
    }
Lines 448-456 int WebSocketHandshake::readStatusLine(c Source/WebCore/websockets/WebSocketHandshake.cpp_sec4
448
        return -1; // We have not received '\n' yet.
461
        return -1; // We have not received '\n' yet.
449
462
450
    const char* end = p + 1;
463
    const char* end = p + 1;
451
    if (end - header > INT_MAX) {
464
    if (end - header > maxLength) {
452
        m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "Status line is too long: " + trimConsoleMessage(header, maxConsoleMessageSize + 1), 0, clientOrigin());
465
        m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "Status line is too long: " + trimConsoleMessage(header, maxConsoleMessageSize + 1), 0, clientOrigin());
453
        return INT_MAX;
466
        return maxLength;
454
    }
467
    }
455
    int lineLength = end - header;
468
    int lineLength = end - header;
456
469
- LayoutTests/ChangeLog +29 lines
Lines 1-3 LayoutTests/ChangeLog_sec1
1
2011-01-09  Joe Mason  <jmason@rim.com>
2
3
        Reviewed by NOBODY (OOPS!).
4
5
        WebSockets: unbounded buffer growth when server sends bad data
6
        https://bugs.webkit.org/show_bug.cgi?id=51253
7
8
        Tests that a websocket handshake should fail after 1024 bytes without a
9
        newline, or if it contains a null byte before the first newline.
10
        
11
        * http/tests/websocket/tests/handshake-fail-by-maxlength-expected.txt: Added.
12
        * http/tests/websocket/tests/handshake-fail-by-maxlength.html: Added.
13
        * http/tests/websocket/tests/handshake-fail-by-maxlength_wsh.py: Added.
14
        * http/tests/websocket/tests/handshake-fail-by-prepended-null-expected.txt: Added.
15
        * http/tests/websocket/tests/handshake-fail-by-prepended-null.html: Added.
16
        * http/tests/websocket/tests/handshake-fail-by-prepended-null_wsh.py: Added.
17
        * http/tests/websocket/tests/script-tests/handshake-fail-by-maxlength.js: Added.
18
        (endTest):
19
        (ws.onopen):
20
        (ws.onmessage):
21
        (ws.onclose):
22
        (timeoutCallback):
23
        * http/tests/websocket/tests/script-tests/handshake-fail-by-prepended-null.js: Added.
24
        (endTest):
25
        (ws.onopen):
26
        (ws.onmessage):
27
        (ws.onclose):
28
        (timeoutCallback):
29
1
2011-01-09  Justin Garcia  <justin.garcia@apple.com>
30
2011-01-09  Justin Garcia  <justin.garcia@apple.com>
2
31
3
        Unreviewed.  Adding svg/text/caret-in-svg-text.xhtml to Skipped list for gtk, where there 
32
        Unreviewed.  Adding svg/text/caret-in-svg-text.xhtml to Skipped list for gtk, where there 
- LayoutTests/http/tests/websocket/tests/handshake-fail-by-maxlength-expected.txt +12 lines
Line 0 LayoutTests/http/tests/websocket/tests/handshake-fail-by-maxlength-expected.txt_sec1
1
CONSOLE MESSAGE: line 0: Status line is too long: ................................................................................................................................…
2
Connection should fail immediately, rather than succeeding or staying in limbo until timeout, if handshake is longer than 1024 bytes.
3
4
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
5
6
PASS timedOut is false
7
PASS connected is false
8
PASS origin is undefined.
9
PASS successfullyParsed is true
10
11
TEST COMPLETE
12
- LayoutTests/http/tests/websocket/tests/handshake-fail-by-maxlength.html +13 lines
Line 0 LayoutTests/http/tests/websocket/tests/handshake-fail-by-maxlength.html_sec1
1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
2
<html>
3
<head>
4
<link rel="stylesheet" href="../../../js-test-resources/js-test-style.css">
5
<script src="../../../js-test-resources/js-test-pre.js"></script>
6
<script src="../../../js-test-resources/js-test-post-function.js"></script>
7
</head>
8
<body>
9
<div id="description"></div>
10
<div id="console"></div>
11
<script src="script-tests/handshake-fail-by-maxlength.js"></script>
12
</body>
13
</html>
- LayoutTests/http/tests/websocket/tests/handshake-fail-by-maxlength_wsh.py +51 lines
Line 0 LayoutTests/http/tests/websocket/tests/handshake-fail-by-maxlength_wsh.py_sec1
1
# Copyright (C) Research In Motion Limited 2011. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or without
4
# modification, are permitted provided that the following conditions are
5
# met:
6
#
7
#     * Redistributions of source code must retain the above copyright
8
# notice, this list of conditions and the following disclaimer.
9
#     * Redistributions in binary form must reproduce the above
10
# copyright notice, this list of conditions and the following disclaimer
11
# in the documentation and/or other materials provided with the
12
# distribution.
13
#     * Neither the name of Google Inc. nor the names of its
14
# contributors may be used to endorse or promote products derived from
15
# this software without specific prior written permission.
16
#
17
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29
import time
30
31
def web_socket_do_extra_handshake(request):
32
    # This will cause the handshake to fail because it pushes the length of the
33
    # status line of 1024 characters
34
    msg = ""
35
    for i in range(0, 1024):
36
        msg += "."
37
    msg += 'HTTP/1.1 101 WebSocket Protocol Handshake\r\n'
38
    msg += 'Upgrade: WebSocket\r\n'
39
    msg += 'Connection: Upgrade\r\n'
40
    msg += 'Sec-WebSocket-Location: ' + request.ws_location + '\r\n'
41
    msg += 'Sec-WebSocket-Origin: ' + request.ws_origin + '\r\n'
42
    msg += '\r\n'
43
    msg += request.ws_challenge_md5
44
    request.connection.write(msg)
45
    # continue writing data until the client disconnects
46
    while True:
47
        time.sleep(1)
48
        request.connection.write('keepalive\n')
49
50
def web_socket_transfer_data(request):
51
    pass
- LayoutTests/http/tests/websocket/tests/handshake-fail-by-prepended-null-expected.txt +12 lines
Line 0 LayoutTests/http/tests/websocket/tests/handshake-fail-by-prepended-null-expected.txt_sec1
1
CONSOLE MESSAGE: line 0: Status line contains embedded null
2
Connection should fail immediately, rather than succeeding or staying in limbo until timeout, if a null byte is received before the handshake.
3
4
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
5
6
PASS timedOut is false
7
PASS connected is false
8
PASS origin is undefined.
9
PASS successfullyParsed is true
10
11
TEST COMPLETE
12
- LayoutTests/http/tests/websocket/tests/handshake-fail-by-prepended-null.html +13 lines
Line 0 LayoutTests/http/tests/websocket/tests/handshake-fail-by-prepended-null.html_sec1
1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
2
<html>
3
<head>
4
<link rel="stylesheet" href="../../../js-test-resources/js-test-style.css">
5
<script src="../../../js-test-resources/js-test-pre.js"></script>
6
<script src="../../../js-test-resources/js-test-post-function.js"></script>
7
</head>
8
<body>
9
<div id="description"></div>
10
<div id="console"></div>
11
<script src="script-tests/handshake-fail-by-prepended-null.js"></script>
12
</body>
13
</html>
- LayoutTests/http/tests/websocket/tests/handshake-fail-by-prepended-null_wsh.py +56 lines
Line 0 LayoutTests/http/tests/websocket/tests/handshake-fail-by-prepended-null_wsh.py_sec1
1
# Copyright (C) Research In Motion Limited 2011. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or without
4
# modification, are permitted provided that the following conditions are
5
# met:
6
#
7
#     * Redistributions of source code must retain the above copyright
8
# notice, this list of conditions and the following disclaimer.
9
#     * Redistributions in binary form must reproduce the above
10
# copyright notice, this list of conditions and the following disclaimer
11
# in the documentation and/or other materials provided with the
12
# distribution.
13
#     * Neither the name of Google Inc. nor the names of its
14
# contributors may be used to endorse or promote products derived from
15
# this software without specific prior written permission.
16
#
17
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29
import time
30
31
def web_socket_do_extra_handshake(request):
32
    # This simulates a broken server that sends a WebSocket frame before the
33
    # handshake, and more frames afterwards.  It is important that if this
34
    # happens the client does not buffer all the frames as the server continues
35
    # to send more data - it should abort after reading a reasonable number of
36
    # bytes (set arbitrarily to 1024).
37
    frame = '\0Frame-contains-thirty-two-bytes'
38
39
    msg = frame
40
    msg += 'HTTP/1.1 101 WebSocket Protocol Handshake\r\n'
41
    msg += 'Upgrade: WebSocket\r\n'
42
    msg += 'Connection: Upgrade\r\n'
43
    msg += 'Sec-WebSocket-Location: ' + request.ws_location + '\r\n'
44
    msg += 'Sec-WebSocket-Origin: ' + request.ws_origin + '\r\n'
45
    msg += '\r\n'
46
    msg += request.ws_challenge_md5
47
    request.connection.write(msg)
48
    # continue writing data until the client disconnects
49
    while True:
50
        time.sleep(1)
51
        numFrames = 1024 / len(frame) # write over 1024 bytes including the above handshake
52
        for i in range(0, numFrames):
53
            request.connection.write(frame)
54
55
def web_socket_transfer_data(request):
56
    pass
- LayoutTests/http/tests/websocket/tests/script-tests/handshake-fail-by-maxlength.js +50 lines
Line 0 LayoutTests/http/tests/websocket/tests/script-tests/handshake-fail-by-maxlength.js_sec1
1
description('Connection should fail immediately, rather than succeeding or staying in limbo until timeout, if handshake is longer than 1024 bytes.');
2
3
if (window.layoutTestController)
4
    layoutTestController.waitUntilDone()
5
6
var timedOut = false;
7
var connected = false;
8
var origin;
9
10
function endTest() {
11
    shouldBeFalse('timedOut');
12
    shouldBeFalse('connected');
13
    shouldBeUndefined('origin');
14
    clearTimeout(timeoutID);
15
    isSuccessfullyParsed();
16
    if (window.layoutTestController)
17
        layoutTestController.notifyDone();
18
}
19
20
var url = 'ws://localhost:8880/websocket/tests/handshake-fail-by-maxlength';
21
var ws = new WebSocket(url);
22
23
ws.onopen = function()
24
{
25
    debug('Connected');
26
    connected = true;
27
}
28
29
ws.onmessage = function(messageEvent)
30
{
31
    origin = messageEvent.data;
32
    debug('origin = ' + origin);
33
    ws.close();
34
}
35
36
ws.onclose = function()
37
{
38
    endTest();
39
}
40
41
function timeoutCallback()
42
{
43
    debug('Timed out (state = ' + ws.readyState + ')');
44
    timedOut = true;
45
    endTest();
46
}
47
48
var timeoutID = setTimeout(timeoutCallback, 3000);
49
50
var successfullyParsed = true;
- LayoutTests/http/tests/websocket/tests/script-tests/handshake-fail-by-prepended-null.js +51 lines
Line 0 LayoutTests/http/tests/websocket/tests/script-tests/handshake-fail-by-prepended-null.js_sec1
1
description('Connection should fail immediately, rather than succeeding or staying in limbo until timeout, if a null byte is received before the handshake.');
2
3
4
if (window.layoutTestController)
5
    layoutTestController.waitUntilDone()
6
7
var timedOut = false;
8
var connected = false;
9
var origin;
10
11
function endTest() {
12
    shouldBeFalse('timedOut');
13
    shouldBeFalse('connected');
14
    shouldBeUndefined('origin');
15
    clearTimeout(timeoutID);
16
    isSuccessfullyParsed();
17
    if (window.layoutTestController)
18
        layoutTestController.notifyDone();
19
}
20
21
var url = 'ws://localhost:8880/websocket/tests/handshake-fail-by-prepended-null';
22
var ws = new WebSocket(url);
23
24
ws.onopen = function()
25
{
26
    debug('Connected');
27
    connected = true;
28
}
29
30
ws.onmessage = function(messageEvent)
31
{
32
    origin = messageEvent.data;
33
    debug('origin = ' + origin);
34
    ws.close();
35
}
36
37
ws.onclose = function()
38
{
39
    endTest();
40
}
41
42
function timeoutCallback()
43
{
44
    debug('Timed out (state = ' + ws.readyState + ')');
45
    timedOut = true;
46
    endTest();
47
}
48
49
var timeoutID = setTimeout(timeoutCallback, 3000);
50
51
var successfullyParsed = true;

Return to Bug 51253