diff --git a/CHANGELOG.md b/CHANGELOG.md index f0b8e77e..2061b51a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Version 149: * pausation always allocates * Don't copy completion handlers * handler_ptr is move-only +* Fix Travis memory utilization API Changes: diff --git a/include/boost/beast/websocket/stream.hpp b/include/boost/beast/websocket/stream.hpp index 0086d817..0e19e391 100644 --- a/include/boost/beast/websocket/stream.hpp +++ b/include/boost/beast/websocket/stream.hpp @@ -123,7 +123,8 @@ class stream friend class close_test; friend class frame_test; friend class ping_test; - friend class read_test; + friend class read1_test; + friend class read2_test; friend class stream_test; friend class write_test; diff --git a/test/beast/websocket/CMakeLists.txt b/test/beast/websocket/CMakeLists.txt index 3ac8cc6c..a0fd7a1f 100644 --- a/test/beast/websocket/CMakeLists.txt +++ b/test/beast/websocket/CMakeLists.txt @@ -26,7 +26,8 @@ add_executable (tests-beast-websocket mask.cpp option.cpp ping.cpp - read.cpp + read1.cpp + read2.cpp rfc6455.cpp role.cpp stream.cpp diff --git a/test/beast/websocket/Jamfile b/test/beast/websocket/Jamfile index c684983d..890562bc 100644 --- a/test/beast/websocket/Jamfile +++ b/test/beast/websocket/Jamfile @@ -16,7 +16,8 @@ local SOURCES = mask.cpp option.cpp ping.cpp - read.cpp + read1.cpp + read2.cpp rfc6455.cpp role.cpp stream.cpp diff --git a/test/beast/websocket/read.cpp b/test/beast/websocket/read1.cpp similarity index 79% rename from test/beast/websocket/read.cpp rename to test/beast/websocket/read1.cpp index 32e43c11..1de53099 100644 --- a/test/beast/websocket/read.cpp +++ b/test/beast/websocket/read1.cpp @@ -20,7 +20,7 @@ namespace boost { namespace beast { namespace websocket { -class read_test : public websocket_test_suite +class read1_test : public websocket_test_suite { public: template @@ -1008,220 +1008,6 @@ public: } } - void - testIssue802() - { - for(std::size_t i = 0; i < 100; ++i) - { - echo_server es{log, kind::async}; - boost::asio::io_context ioc; - stream ws{ioc}; - ws.next_layer().connect(es.stream()); - ws.handshake("localhost", "/"); - // too-big message frame indicates payload of 2^64-1 - boost::asio::write(ws.next_layer(), sbuf( - "\x81\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff")); - multi_buffer b; - error_code ec; - ws.read(b, ec); - BEAST_EXPECT(ec == error::closed); - BEAST_EXPECT(ws.reason().code == 1009); - } - } - - void - testIssue807() - { - echo_server es{log}; - boost::asio::io_context ioc; - stream ws{ioc}; - ws.next_layer().connect(es.stream()); - ws.handshake("localhost", "/"); - ws.write(sbuf("Hello, world!")); - char buf[4]; - boost::asio::mutable_buffer b{buf, 0}; - auto const n = ws.read_some(b); - BEAST_EXPECT(n == 0); - } - - /* Bishop Fox Hybrid Assessment issue 1 - - Happens with permessage-deflate enabled and a - compressed frame with the FIN bit set ends with an - invalid prefix. - */ - void - testIssueBF1() - { - permessage_deflate pmd; - pmd.client_enable = true; - pmd.server_enable = true; - - // read -#if 0 - { - echo_server es{log}; - boost::asio::io_context ioc; - stream ws{ioc}; - ws.set_option(pmd); - ws.next_layer().connect(es.stream()); - ws.handshake("localhost", "/"); - // invalid 1-byte deflate block in frame - boost::asio::write(ws.next_layer(), sbuf( - "\xc1\x81\x3a\xa1\x74\x3b\x49")); - } -#endif - { - boost::asio::io_context ioc; - stream wsc{ioc}; - stream wss{ioc}; - wsc.set_option(pmd); - wss.set_option(pmd); - wsc.next_layer().connect(wss.next_layer()); - wsc.async_handshake( - "localhost", "/", [](error_code){}); - wss.async_accept([](error_code){}); - ioc.run(); - ioc.restart(); - BEAST_EXPECT(wsc.is_open()); - BEAST_EXPECT(wss.is_open()); - // invalid 1-byte deflate block in frame - boost::asio::write(wsc.next_layer(), sbuf( - "\xc1\x81\x3a\xa1\x74\x3b\x49")); - error_code ec; - multi_buffer b; - wss.read(b, ec); - BEAST_EXPECTS(ec == zlib::error::end_of_stream, ec.message()); - } - - // async read -#if 0 - { - echo_server es{log, kind::async}; - boost::asio::io_context ioc; - stream ws{ioc}; - ws.set_option(pmd); - ws.next_layer().connect(es.stream()); - ws.handshake("localhost", "/"); - // invalid 1-byte deflate block in frame - boost::asio::write(ws.next_layer(), sbuf( - "\xc1\x81\x3a\xa1\x74\x3b\x49")); - } -#endif - { - boost::asio::io_context ioc; - stream wsc{ioc}; - stream wss{ioc}; - wsc.set_option(pmd); - wss.set_option(pmd); - wsc.next_layer().connect(wss.next_layer()); - wsc.async_handshake( - "localhost", "/", [](error_code){}); - wss.async_accept([](error_code){}); - ioc.run(); - ioc.restart(); - BEAST_EXPECT(wsc.is_open()); - BEAST_EXPECT(wss.is_open()); - // invalid 1-byte deflate block in frame - boost::asio::write(wsc.next_layer(), sbuf( - "\xc1\x81\x3a\xa1\x74\x3b\x49")); - error_code ec; - flat_buffer b; - wss.async_read(b, - [&ec](error_code ec_, std::size_t){ ec = ec_; }); - ioc.run(); - BEAST_EXPECTS(ec == zlib::error::end_of_stream, ec.message()); - } - } - - /* Bishop Fox Hybrid Assessment issue 2 - - Happens with permessage-deflate enabled, - and a deflate block with the BFINAL bit set - is encountered in a compressed payload. - */ - void - testIssueBF2() - { - permessage_deflate pmd; - pmd.client_enable = true; - pmd.server_enable = true; - - // read - { - boost::asio::io_context ioc; - stream wsc{ioc}; - stream wss{ioc}; - wsc.set_option(pmd); - wss.set_option(pmd); - wsc.next_layer().connect(wss.next_layer()); - wsc.async_handshake( - "localhost", "/", [](error_code){}); - wss.async_accept([](error_code){}); - ioc.run(); - ioc.restart(); - BEAST_EXPECT(wsc.is_open()); - BEAST_EXPECT(wss.is_open()); - // contains a deflate block with BFINAL set - boost::asio::write(wsc.next_layer(), sbuf( - "\xc1\xf8\xd1\xe4\xcc\x3e\xda\xe4\xcc\x3e" - "\x2b\x1e\x36\xc4\x2b\x1e\x36\xc4\x2b\x1e" - "\x36\x3e\x35\xae\x4f\x54\x18\xae\x4f\x7b" - "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4" - "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e" - "\xd1\x1e\x36\xc4\x2b\x1e\x36\xc4\x2b\xe4" - "\x28\x74\x52\x8e\x05\x74\x52\xa1\xcc\x3e" - "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4" - "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e" - "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4" - "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\x36\x3e" - "\xd1\xec\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4" - "\xcc\x3e\xd1\xe4\xcc\x3e")); - error_code ec; - flat_buffer b; - wss.read(b, ec); - BEAST_EXPECTS(ec == zlib::error::end_of_stream, ec.message()); - } - - // async read - { - boost::asio::io_context ioc; - stream wsc{ioc}; - stream wss{ioc}; - wsc.set_option(pmd); - wss.set_option(pmd); - wsc.next_layer().connect(wss.next_layer()); - wsc.async_handshake( - "localhost", "/", [](error_code){}); - wss.async_accept([](error_code){}); - ioc.run(); - ioc.restart(); - BEAST_EXPECT(wsc.is_open()); - BEAST_EXPECT(wss.is_open()); - // contains a deflate block with BFINAL set - boost::asio::write(wsc.next_layer(), sbuf( - "\xc1\xf8\xd1\xe4\xcc\x3e\xda\xe4\xcc\x3e" - "\x2b\x1e\x36\xc4\x2b\x1e\x36\xc4\x2b\x1e" - "\x36\x3e\x35\xae\x4f\x54\x18\xae\x4f\x7b" - "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4" - "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e" - "\xd1\x1e\x36\xc4\x2b\x1e\x36\xc4\x2b\xe4" - "\x28\x74\x52\x8e\x05\x74\x52\xa1\xcc\x3e" - "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4" - "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e" - "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4" - "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\x36\x3e" - "\xd1\xec\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4" - "\xcc\x3e\xd1\xe4\xcc\x3e")); - error_code ec; - flat_buffer b; - wss.async_read(b, - [&ec](error_code ec_, std::size_t){ ec = ec_; }); - ioc.run(); - BEAST_EXPECTS(ec == zlib::error::end_of_stream, ec.message()); - } - } - void run() override { @@ -1229,14 +1015,10 @@ public: testSuspend(); testParseFrame(); testContHook(); - testIssue802(); - testIssue807(); - testIssueBF1(); - testIssueBF2(); } }; -BEAST_DEFINE_TESTSUITE(beast,websocket,read); +BEAST_DEFINE_TESTSUITE(beast,websocket,read1); } // websocket } // beast diff --git a/test/beast/websocket/read2.cpp b/test/beast/websocket/read2.cpp new file mode 100644 index 00000000..3cc1f232 --- /dev/null +++ b/test/beast/websocket/read2.cpp @@ -0,0 +1,254 @@ +// +// Copyright (w) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/boostorg/beast +// + +// Test that header file is self-contained. +#include + +#include "test.hpp" + +#include + +#include + +namespace boost { +namespace beast { +namespace websocket { + +class read2_test : public websocket_test_suite +{ +public: + void + testIssue802() + { + for(std::size_t i = 0; i < 100; ++i) + { + echo_server es{log, kind::async}; + boost::asio::io_context ioc; + stream ws{ioc}; + ws.next_layer().connect(es.stream()); + ws.handshake("localhost", "/"); + // too-big message frame indicates payload of 2^64-1 + boost::asio::write(ws.next_layer(), sbuf( + "\x81\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff")); + multi_buffer b; + error_code ec; + ws.read(b, ec); + BEAST_EXPECT(ec == error::closed); + BEAST_EXPECT(ws.reason().code == 1009); + } + } + + void + testIssue807() + { + echo_server es{log}; + boost::asio::io_context ioc; + stream ws{ioc}; + ws.next_layer().connect(es.stream()); + ws.handshake("localhost", "/"); + ws.write(sbuf("Hello, world!")); + char buf[4]; + boost::asio::mutable_buffer b{buf, 0}; + auto const n = ws.read_some(b); + BEAST_EXPECT(n == 0); + } + + /* Bishop Fox Hybrid Assessment issue 1 + + Happens with permessage-deflate enabled and a + compressed frame with the FIN bit set ends with an + invalid prefix. + */ + void + testIssueBF1() + { + permessage_deflate pmd; + pmd.client_enable = true; + pmd.server_enable = true; + + // read +#if 0 + { + echo_server es{log}; + boost::asio::io_context ioc; + stream ws{ioc}; + ws.set_option(pmd); + ws.next_layer().connect(es.stream()); + ws.handshake("localhost", "/"); + // invalid 1-byte deflate block in frame + boost::asio::write(ws.next_layer(), sbuf( + "\xc1\x81\x3a\xa1\x74\x3b\x49")); + } +#endif + { + boost::asio::io_context ioc; + stream wsc{ioc}; + stream wss{ioc}; + wsc.set_option(pmd); + wss.set_option(pmd); + wsc.next_layer().connect(wss.next_layer()); + wsc.async_handshake( + "localhost", "/", [](error_code){}); + wss.async_accept([](error_code){}); + ioc.run(); + ioc.restart(); + BEAST_EXPECT(wsc.is_open()); + BEAST_EXPECT(wss.is_open()); + // invalid 1-byte deflate block in frame + boost::asio::write(wsc.next_layer(), sbuf( + "\xc1\x81\x3a\xa1\x74\x3b\x49")); + error_code ec; + multi_buffer b; + wss.read(b, ec); + BEAST_EXPECTS(ec == zlib::error::end_of_stream, ec.message()); + } + + // async read +#if 0 + { + echo_server es{log, kind::async}; + boost::asio::io_context ioc; + stream ws{ioc}; + ws.set_option(pmd); + ws.next_layer().connect(es.stream()); + ws.handshake("localhost", "/"); + // invalid 1-byte deflate block in frame + boost::asio::write(ws.next_layer(), sbuf( + "\xc1\x81\x3a\xa1\x74\x3b\x49")); + } +#endif + { + boost::asio::io_context ioc; + stream wsc{ioc}; + stream wss{ioc}; + wsc.set_option(pmd); + wss.set_option(pmd); + wsc.next_layer().connect(wss.next_layer()); + wsc.async_handshake( + "localhost", "/", [](error_code){}); + wss.async_accept([](error_code){}); + ioc.run(); + ioc.restart(); + BEAST_EXPECT(wsc.is_open()); + BEAST_EXPECT(wss.is_open()); + // invalid 1-byte deflate block in frame + boost::asio::write(wsc.next_layer(), sbuf( + "\xc1\x81\x3a\xa1\x74\x3b\x49")); + error_code ec; + flat_buffer b; + wss.async_read(b, + [&ec](error_code ec_, std::size_t){ ec = ec_; }); + ioc.run(); + BEAST_EXPECTS(ec == zlib::error::end_of_stream, ec.message()); + } + } + + /* Bishop Fox Hybrid Assessment issue 2 + + Happens with permessage-deflate enabled, + and a deflate block with the BFINAL bit set + is encountered in a compressed payload. + */ + void + testIssueBF2() + { + permessage_deflate pmd; + pmd.client_enable = true; + pmd.server_enable = true; + + // read + { + boost::asio::io_context ioc; + stream wsc{ioc}; + stream wss{ioc}; + wsc.set_option(pmd); + wss.set_option(pmd); + wsc.next_layer().connect(wss.next_layer()); + wsc.async_handshake( + "localhost", "/", [](error_code){}); + wss.async_accept([](error_code){}); + ioc.run(); + ioc.restart(); + BEAST_EXPECT(wsc.is_open()); + BEAST_EXPECT(wss.is_open()); + // contains a deflate block with BFINAL set + boost::asio::write(wsc.next_layer(), sbuf( + "\xc1\xf8\xd1\xe4\xcc\x3e\xda\xe4\xcc\x3e" + "\x2b\x1e\x36\xc4\x2b\x1e\x36\xc4\x2b\x1e" + "\x36\x3e\x35\xae\x4f\x54\x18\xae\x4f\x7b" + "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4" + "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e" + "\xd1\x1e\x36\xc4\x2b\x1e\x36\xc4\x2b\xe4" + "\x28\x74\x52\x8e\x05\x74\x52\xa1\xcc\x3e" + "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4" + "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e" + "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4" + "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\x36\x3e" + "\xd1\xec\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4" + "\xcc\x3e\xd1\xe4\xcc\x3e")); + error_code ec; + flat_buffer b; + wss.read(b, ec); + BEAST_EXPECTS(ec == zlib::error::end_of_stream, ec.message()); + } + + // async read + { + boost::asio::io_context ioc; + stream wsc{ioc}; + stream wss{ioc}; + wsc.set_option(pmd); + wss.set_option(pmd); + wsc.next_layer().connect(wss.next_layer()); + wsc.async_handshake( + "localhost", "/", [](error_code){}); + wss.async_accept([](error_code){}); + ioc.run(); + ioc.restart(); + BEAST_EXPECT(wsc.is_open()); + BEAST_EXPECT(wss.is_open()); + // contains a deflate block with BFINAL set + boost::asio::write(wsc.next_layer(), sbuf( + "\xc1\xf8\xd1\xe4\xcc\x3e\xda\xe4\xcc\x3e" + "\x2b\x1e\x36\xc4\x2b\x1e\x36\xc4\x2b\x1e" + "\x36\x3e\x35\xae\x4f\x54\x18\xae\x4f\x7b" + "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4" + "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e" + "\xd1\x1e\x36\xc4\x2b\x1e\x36\xc4\x2b\xe4" + "\x28\x74\x52\x8e\x05\x74\x52\xa1\xcc\x3e" + "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4" + "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e" + "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4" + "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\x36\x3e" + "\xd1\xec\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4" + "\xcc\x3e\xd1\xe4\xcc\x3e")); + error_code ec; + flat_buffer b; + wss.async_read(b, + [&ec](error_code ec_, std::size_t){ ec = ec_; }); + ioc.run(); + BEAST_EXPECTS(ec == zlib::error::end_of_stream, ec.message()); + } + } + + void + run() override + { + testIssue802(); + testIssue807(); + testIssueBF1(); + testIssueBF2(); + } +}; + +BEAST_DEFINE_TESTSUITE(beast,websocket,read2); + +} // websocket +} // beast +} // boost