diff --git a/test/processors/hybi00.cpp b/test/processors/hybi00.cpp index 65b5f55750..de5a4e6de6 100644 --- a/test/processors/hybi00.cpp +++ b/test/processors/hybi00.cpp @@ -45,6 +45,8 @@ struct stub_config { message_type; typedef websocketpp::message_buffer::alloc::con_msg_manager con_msg_manager_type; + + static const size_t max_message_size = 16000000; }; struct processor_setup { diff --git a/test/processors/hybi07.cpp b/test/processors/hybi07.cpp index 2cddc8a52a..59668082aa 100644 --- a/test/processors/hybi07.cpp +++ b/test/processors/hybi07.cpp @@ -50,6 +50,8 @@ struct stub_config { typedef websocketpp::random::none::int_generator rng_type; + static const size_t max_message_size = 16000000; + /// Extension related config static const bool enable_extensions = false; diff --git a/test/processors/hybi08.cpp b/test/processors/hybi08.cpp index 60da59e797..369de77db8 100644 --- a/test/processors/hybi08.cpp +++ b/test/processors/hybi08.cpp @@ -50,6 +50,8 @@ struct stub_config { typedef websocketpp::random::none::int_generator rng_type; + static const size_t max_message_size = 16000000; + /// Extension related config static const bool enable_extensions = false; diff --git a/test/processors/hybi13.cpp b/test/processors/hybi13.cpp index 0cacb567a7..e4c1bff2f9 100644 --- a/test/processors/hybi13.cpp +++ b/test/processors/hybi13.cpp @@ -60,6 +60,7 @@ struct stub_config { typedef websocketpp::extensions::permessage_deflate::disabled permessage_deflate_type; + static const size_t max_message_size = 16000000; static const bool enable_extensions = false; }; @@ -81,6 +82,7 @@ struct stub_config_ext { typedef websocketpp::extensions::permessage_deflate::enabled permessage_deflate_type; + static const size_t max_message_size = 16000000; static const bool enable_extensions = true; }; @@ -489,6 +491,36 @@ BOOST_AUTO_TEST_CASE( prepare_data_frame ) { } +BOOST_AUTO_TEST_CASE( single_frame_message_too_large ) { + processor_setup env(true); + + env.p.set_max_message_size(3); + + uint8_t frame0[10] = {0x82, 0x84, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01}; + + // read message that is one byte too large + BOOST_CHECK_EQUAL( env.p.consume(frame0,10,env.ec), 6 ); + BOOST_CHECK_EQUAL( env.ec, websocketpp::processor::error::message_too_big ); +} + +BOOST_AUTO_TEST_CASE( multiple_frame_message_too_large ) { + processor_setup env(true); + + env.p.set_max_message_size(4); + + uint8_t frame0[8] = {0x02, 0x82, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01}; + uint8_t frame1[9] = {0x80, 0x83, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01}; + + // read first message frame with size under the limit + BOOST_CHECK_EQUAL( env.p.consume(frame0,8,env.ec), 8 ); + BOOST_CHECK( !env.ec ); + + // read second message frame that puts the size over the limit + BOOST_CHECK_EQUAL( env.p.consume(frame1,9,env.ec), 6 ); + BOOST_CHECK_EQUAL( env.ec, websocketpp::processor::error::message_too_big ); +} + + BOOST_AUTO_TEST_CASE( client_handshake_request ) { processor_setup env(false); diff --git a/test/processors/processor.cpp b/test/processors/processor.cpp index aa3c038b2c..0505646616 100644 --- a/test/processors/processor.cpp +++ b/test/processors/processor.cpp @@ -132,4 +132,4 @@ BOOST_AUTO_TEST_CASE( version_non_numeric ) { r.consume(handshake.c_str(),handshake.size()); BOOST_CHECK(websocketpp::processor::get_websocket_version(r) == -1); -} +} \ No newline at end of file diff --git a/websocketpp/config/core.hpp b/websocketpp/config/core.hpp index e400da5025..32ddb3ebec 100644 --- a/websocketpp/config/core.hpp +++ b/websocketpp/config/core.hpp @@ -215,6 +215,18 @@ struct core { */ static const bool silent_close = false; + /// Default maximum message size + /** + * Default value for the processor's maximum message size. Maximum message size + * determines the point at which the library will fail a connection with the + * message_too_big protocol error. + * + * The default is 32MB + * + * @since 0.4.0-alpha1 + */ + static const size_t max_message_size = 32000000; + /// Global flag for enabling/disabling extensions static const bool enable_extensions = true; diff --git a/websocketpp/config/core_client.hpp b/websocketpp/config/core_client.hpp index 328bcc867c..51cfa85c79 100644 --- a/websocketpp/config/core_client.hpp +++ b/websocketpp/config/core_client.hpp @@ -216,6 +216,18 @@ struct core_client { */ static const bool silent_close = false; + /// Default maximum message size + /** + * Default value for the processor's maximum message size. Maximum message size + * determines the point at which the library will fail a connection with the + * message_too_big protocol error. + * + * The default is 32MB + * + * @since 0.4.0-alpha1 + */ + static const size_t max_message_size = 32000000; + /// Global flag for enabling/disabling extensions static const bool enable_extensions = true; diff --git a/websocketpp/processors/hybi13.hpp b/websocketpp/processors/hybi13.hpp index d7d1a1edfe..14b2d3fa9d 100644 --- a/websocketpp/processors/hybi13.hpp +++ b/websocketpp/processors/hybi13.hpp @@ -369,11 +369,25 @@ public: m_current_msg = &m_control_msg; } else { if (!m_data_msg.msg_ptr) { + if (m_bytes_needed > base::m_max_message_size) { + ec = make_error_code(error::message_too_big); + break; + } + m_data_msg = msg_metadata( m_msg_manager->get_message(op,m_bytes_needed), frame::get_masking_key(m_basic_header,m_extended_header) ); } else { + // Fetch the underlying payload buffer from the data message we + // are writing into. + std::string & out = m_data_msg.msg_ptr->get_raw_payload(); + + if (out.size() + m_bytes_needed > base::m_max_message_size) { + ec = make_error_code(error::message_too_big); + break; + } + // Each frame starts a new masking key. All other state // remains between frames. m_data_msg.prepared_key = prepare_masking_key( diff --git a/websocketpp/processors/processor.hpp b/websocketpp/processors/processor.hpp index 505b0e3c3d..69b9ab186a 100644 --- a/websocketpp/processors/processor.hpp +++ b/websocketpp/processors/processor.hpp @@ -161,13 +161,43 @@ public: explicit processor(bool secure, bool p_is_server) : m_secure(secure) - , m_server(p_is_server) {} + , m_server(p_is_server) + , m_max_message_size(config::max_message_size) + {} virtual ~processor() {} /// Get the protocol version of this processor virtual int get_version() const = 0; + /// Get maximum message size + /** + * Get maximum message size. Maximum message size determines the point at which the + * processor will fail a connection with the message_too_big protocol error. + * + * The default is retrieved from the max_message_size value from the template config + * + * @since 0.4.0-alpha1 + */ + size_t get_max_message_size() const { + return m_max_message_size; + } + + /// Set maximum message size + /** + * Set maximum message size. Maximum message size determines the point at which the + * processor will fail a connection with the message_too_big protocol error. + * + * The default is retrieved from the max_message_size value from the template config + * + * @since 0.4.0-alpha1 + * + * @param new_value The value to set as the maximum message size. + */ + void set_max_message_size(size_t new_value) { + m_max_message_size = new_value; + } + /// Returns whether or not the permessage_compress extension is implemented /** * Compile time flag that indicates whether this processor has implemented @@ -358,6 +388,7 @@ public: protected: bool const m_secure; bool const m_server; + size_t m_max_message_size; }; } // namespace processor