diff options
Diffstat (limited to 'WebCore/websockets')
-rw-r--r-- | WebCore/websockets/WebSocket.h | 2 | ||||
-rw-r--r-- | WebCore/websockets/WebSocketChannel.cpp | 77 | ||||
-rw-r--r-- | WebCore/websockets/WebSocketChannel.h | 7 | ||||
-rw-r--r-- | WebCore/websockets/WebSocketHandshake.cpp | 2 | ||||
-rw-r--r-- | WebCore/websockets/WebSocketHandshakeResponse.cpp | 2 |
5 files changed, 65 insertions, 25 deletions
diff --git a/WebCore/websockets/WebSocket.h b/WebCore/websockets/WebSocket.h index 15508b4..fd3ee56 100644 --- a/WebCore/websockets/WebSocket.h +++ b/WebCore/websockets/WebSocket.h @@ -34,7 +34,6 @@ #if ENABLE(WEB_SOCKETS) #include "ActiveDOMObject.h" -#include "AtomicStringHash.h" #include "EventListener.h" #include "EventNames.h" #include "EventTarget.h" @@ -43,6 +42,7 @@ #include <wtf/Forward.h> #include <wtf/OwnPtr.h> #include <wtf/RefCounted.h> +#include <wtf/text/AtomicStringHash.h> namespace WebCore { diff --git a/WebCore/websockets/WebSocketChannel.cpp b/WebCore/websockets/WebSocketChannel.cpp index 5859fd7..54be16a 100644 --- a/WebCore/websockets/WebSocketChannel.cpp +++ b/WebCore/websockets/WebSocketChannel.cpp @@ -41,11 +41,11 @@ #include "ScriptExecutionContext.h" #include "SocketStreamError.h" #include "SocketStreamHandle.h" -#include "StringHash.h" #include "WebSocketChannelClient.h" #include "WebSocketHandshake.h" #include <wtf/text/CString.h> +#include <wtf/text/StringHash.h> #include <wtf/Deque.h> #include <wtf/FastMalloc.h> #include <wtf/HashMap.h> @@ -61,6 +61,7 @@ WebSocketChannel::WebSocketChannel(ScriptExecutionContext* context, WebSocketCha , m_resumeTimer(this, &WebSocketChannel::resumeTimerFired) , m_suspended(false) , m_closed(false) + , m_shouldDiscardReceivedData(false) , m_unhandledBufferedAmount(0) { } @@ -171,10 +172,14 @@ void WebSocketChannel::didReceiveData(SocketStreamHandle* handle, const char* da return; } if (!m_client) { + m_shouldDiscardReceivedData = true; handle->close(); return; } + if (m_shouldDiscardReceivedData) + return; if (!appendToBuffer(data, len)) { + m_shouldDiscardReceivedData = true; handle->close(); return; } @@ -187,6 +192,7 @@ void WebSocketChannel::didFail(SocketStreamHandle* handle, const SocketStreamErr { LOG(Network, "WebSocketChannel %p didFail", this); ASSERT(handle == m_handle || !m_handle); + m_shouldDiscardReceivedData = true; handle->close(); } @@ -198,23 +204,28 @@ void WebSocketChannel::didCancelAuthenticationChallenge(SocketStreamHandle*, con { } -bool WebSocketChannel::appendToBuffer(const char* data, int len) +bool WebSocketChannel::appendToBuffer(const char* data, size_t len) { + size_t newBufferSize = m_bufferSize + len; + if (newBufferSize < m_bufferSize) { + LOG(Network, "WebSocket buffer overflow (%lu+%lu)", static_cast<unsigned long>(m_bufferSize), static_cast<unsigned long>(len)); + return false; + } char* newBuffer = 0; - if (tryFastMalloc(m_bufferSize + len).getValue(newBuffer)) { + if (tryFastMalloc(newBufferSize).getValue(newBuffer)) { if (m_buffer) memcpy(newBuffer, m_buffer, m_bufferSize); memcpy(newBuffer + m_bufferSize, data, len); fastFree(m_buffer); m_buffer = newBuffer; - m_bufferSize += len; + m_bufferSize = newBufferSize; return true; } - m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, String::format("WebSocket frame (at %d bytes) is too long.", m_bufferSize + len), 0, m_handshake.clientOrigin()); + m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, String::format("WebSocket frame (at %lu bytes) is too long.", static_cast<unsigned long>(newBufferSize)), 0, m_handshake.clientOrigin()); return false; } -void WebSocketChannel::skipBuffer(int len) +void WebSocketChannel::skipBuffer(size_t len) { ASSERT(len <= m_bufferSize); m_bufferSize -= len; @@ -231,6 +242,8 @@ bool WebSocketChannel::processBuffer() ASSERT(!m_suspended); ASSERT(m_client); ASSERT(m_buffer); + if (m_shouldDiscardReceivedData) + return false; if (m_handshake.mode() == WebSocketHandshake::Incomplete) { int headerLength = m_handshake.readServerHandshake(m_buffer, m_bufferSize); @@ -250,11 +263,12 @@ bool WebSocketChannel::processBuffer() LOG(Network, "WebSocketChannel %p connected", this); skipBuffer(headerLength); m_client->didConnect(); - LOG(Network, "remaining in read buf %ul", m_bufferSize); + LOG(Network, "remaining in read buf %lu", static_cast<unsigned long>(m_bufferSize)); return m_buffer; } LOG(Network, "WebSocketChannel %p connection failed", this); skipBuffer(headerLength); + m_shouldDiscardReceivedData = true; if (!m_closed) m_handle->close(); return false; @@ -268,27 +282,52 @@ bool WebSocketChannel::processBuffer() unsigned char frameByte = static_cast<unsigned char>(*p++); if ((frameByte & 0x80) == 0x80) { - int length = 0; + size_t length = 0; + bool errorFrame = false; while (p < end) { - if (length > std::numeric_limits<int>::max() / 128) { - LOG(Network, "frame length overflow %d", length); - skipBuffer(p + length - m_buffer); - m_client->didReceiveMessageError(); - if (!m_client) - return false; - if (!m_closed) - m_handle->close(); - return false; + if (length > std::numeric_limits<size_t>::max() / 128) { + LOG(Network, "frame length overflow %lu", static_cast<unsigned long>(length)); + errorFrame = true; + break; + } + size_t newLength = length * 128; + unsigned char msgByte = static_cast<unsigned char>(*p); + unsigned int lengthMsgByte = msgByte & 0x7f; + if (newLength > std::numeric_limits<size_t>::max() - lengthMsgByte) { + LOG(Network, "frame length overflow %lu+%u", static_cast<unsigned long>(newLength), lengthMsgByte); + errorFrame = true; + break; } - char msgByte = *p; - length = length * 128 + (msgByte & 0x7f); + newLength += lengthMsgByte; + if (newLength < length) { // sanity check + LOG(Network, "frame length integer wrap %lu->%lu", static_cast<unsigned long>(length), static_cast<unsigned long>(newLength)); + errorFrame = true; + break; + } + length = newLength; ++p; if (!(msgByte & 0x80)) break; } + if (p + length < p) { + LOG(Network, "frame buffer pointer wrap %p+%lu->%p", p, static_cast<unsigned long>(length), p + length); + errorFrame = true; + } + if (errorFrame) { + skipBuffer(m_bufferSize); // Save memory. + m_shouldDiscardReceivedData = true; + m_client->didReceiveMessageError(); + if (!m_client) + return false; + if (!m_closed) + m_handle->close(); + return false; + } + ASSERT(p + length >= p); if (p + length < end) { p += length; nextFrame = p; + ASSERT(nextFrame > m_buffer); skipBuffer(nextFrame - m_buffer); m_client->didReceiveMessageError(); return m_buffer; diff --git a/WebCore/websockets/WebSocketChannel.h b/WebCore/websockets/WebSocketChannel.h index 893b4c6..43d431a 100644 --- a/WebCore/websockets/WebSocketChannel.h +++ b/WebCore/websockets/WebSocketChannel.h @@ -79,8 +79,8 @@ namespace WebCore { private: WebSocketChannel(ScriptExecutionContext*, WebSocketChannelClient*, const KURL&, const String& protocol); - bool appendToBuffer(const char* data, int len); - void skipBuffer(int len); + bool appendToBuffer(const char* data, size_t len); + void skipBuffer(size_t len); bool processBuffer(); void resumeTimerFired(Timer<WebSocketChannel>* timer); @@ -89,11 +89,12 @@ namespace WebCore { WebSocketHandshake m_handshake; RefPtr<SocketStreamHandle> m_handle; char* m_buffer; - int m_bufferSize; + size_t m_bufferSize; Timer<WebSocketChannel> m_resumeTimer; bool m_suspended; bool m_closed; + bool m_shouldDiscardReceivedData; unsigned long m_unhandledBufferedAmount; }; diff --git a/WebCore/websockets/WebSocketHandshake.cpp b/WebCore/websockets/WebSocketHandshake.cpp index 7711604..effbb67 100644 --- a/WebCore/websockets/WebSocketHandshake.cpp +++ b/WebCore/websockets/WebSocketHandshake.cpp @@ -34,7 +34,6 @@ #include "WebSocketHandshake.h" -#include "AtomicString.h" #include "CharacterNames.h" #include "Cookie.h" #include "CookieJar.h" @@ -51,6 +50,7 @@ #include <wtf/StdLibExtras.h> #include <wtf/StringExtras.h> #include <wtf/Vector.h> +#include <wtf/text/AtomicString.h> #include <wtf/text/CString.h> namespace WebCore { diff --git a/WebCore/websockets/WebSocketHandshakeResponse.cpp b/WebCore/websockets/WebSocketHandshakeResponse.cpp index 753cecf..2e0dad7 100644 --- a/WebCore/websockets/WebSocketHandshakeResponse.cpp +++ b/WebCore/websockets/WebSocketHandshakeResponse.cpp @@ -34,8 +34,8 @@ #include "WebSocketHandshakeResponse.h" -#include "AtomicString.h" #include <wtf/Assertions.h> +#include <wtf/text/AtomicString.h> using namespace std; |