Modified: trunk/Source/WebCore/ChangeLog (147937 => 147938)
--- trunk/Source/WebCore/ChangeLog 2013-04-08 18:09:01 UTC (rev 147937)
+++ trunk/Source/WebCore/ChangeLog 2013-04-08 18:17:19 UTC (rev 147938)
@@ -1,3 +1,27 @@
+2013-04-08 Alexey Proskuryakov <[email protected]>
+
+ <rdar://problem/12834449> Crashes in WebSocketChannel::processFrame when processing a ping
+ https://bugs.webkit.org/show_bug.cgi?id=114178
+
+ Reviewed by Brady Eidson.
+
+ No test, I could never reproduce even manually.
+
+ Calling enqueueRawFrame() could change incoming buffer, so a subsequent skipBuffer()
+ would operate on wrong assumptions. This happened because enqueueRawFrame() actually
+ tried to process the queue, and send failure sometimed clears m_buffer.
+
+ Fixing this by decoupling enqueuing from sending, and making sure that skipBuffer()
+ in ping frame processing case is performed at a safe time.
+
+ * Modules/websockets/WebSocketChannel.cpp:
+ (WebCore::WebSocketChannel::send):
+ (WebCore::WebSocketChannel::startClosingHandshake):
+ (WebCore::WebSocketChannel::processFrame):
+ (WebCore::WebSocketChannel::enqueueTextFrame):
+ (WebCore::WebSocketChannel::enqueueRawFrame):
+ (WebCore::WebSocketChannel::enqueueBlobFrame):
+
2013-04-08 Max Vujovic <[email protected]>
REGRESSION (r147502): Animations of CA filters broken
Modified: trunk/Source/WebCore/Modules/websockets/WebSocketChannel.cpp (147937 => 147938)
--- trunk/Source/WebCore/Modules/websockets/WebSocketChannel.cpp 2013-04-08 18:09:01 UTC (rev 147937)
+++ trunk/Source/WebCore/Modules/websockets/WebSocketChannel.cpp 2013-04-08 18:17:19 UTC (rev 147938)
@@ -140,6 +140,7 @@
LOG(Network, "WebSocketChannel %p send() Sending String '%s'", this, message.utf8().data());
CString utf8 = message.utf8(String::StrictConversionReplacingUnpairedSurrogatesWithFFFD);
enqueueTextFrame(utf8);
+ processOutgoingFrameQueue();
// According to WebSocket API specification, WebSocket.send() should return void instead
// of boolean. However, our implementation still returns boolean due to compatibility
// concern (see bug 65850).
@@ -153,6 +154,7 @@
{
LOG(Network, "WebSocketChannel %p send() Sending ArrayBuffer %p byteOffset=%u byteLength=%u", this, &binaryData, byteOffset, byteLength);
enqueueRawFrame(WebSocketFrame::OpCodeBinary, static_cast<const char*>(binaryData.data()) + byteOffset, byteLength);
+ processOutgoingFrameQueue();
return ThreadableWebSocketChannel::SendSuccess;
}
@@ -160,6 +162,7 @@
{
LOG(Network, "WebSocketChannel %p send() Sending Blob '%s'", this, binaryData.url().elidedString().utf8().data());
enqueueBlobFrame(WebSocketFrame::OpCodeBinary, binaryData);
+ processOutgoingFrameQueue();
return ThreadableWebSocketChannel::SendSuccess;
}
@@ -167,6 +170,7 @@
{
LOG(Network, "WebSocketChannel %p send() Sending char* data="" length=%d", this, data, length);
enqueueRawFrame(WebSocketFrame::OpCodeBinary, data, length);
+ processOutgoingFrameQueue();
return true;
}
@@ -479,6 +483,7 @@
buf.append(reason.utf8().data(), reason.utf8().length());
}
enqueueRawFrame(WebSocketFrame::OpCodeClose, buf.data(), buf.size());
+ processOutgoingFrameQueue();
m_closing = true;
if (m_client)
@@ -658,6 +663,7 @@
case WebSocketFrame::OpCodePing:
enqueueRawFrame(WebSocketFrame::OpCodePong, frame.payload, frame.payloadLength);
skipBuffer(frameEnd - m_buffer.data());
+ processOutgoingFrameQueue();
break;
case WebSocketFrame::OpCodePong:
@@ -683,7 +689,6 @@
frame->frameType = QueuedFrameTypeString;
frame->stringData = string;
m_outgoingFrameQueue.append(frame.release());
- processOutgoingFrameQueue();
}
void WebSocketChannel::enqueueRawFrame(WebSocketFrame::OpCode opCode, const char* data, size_t dataLength)
@@ -696,7 +701,6 @@
if (dataLength)
memcpy(frame->vectorData.data(), data, dataLength);
m_outgoingFrameQueue.append(frame.release());
- processOutgoingFrameQueue();
}
void WebSocketChannel::enqueueBlobFrame(WebSocketFrame::OpCode opCode, const Blob& blob)
@@ -707,7 +711,6 @@
frame->frameType = QueuedFrameTypeBlob;
frame->blobData = Blob::create(blob.url(), blob.type(), blob.size());
m_outgoingFrameQueue.append(frame.release());
- processOutgoingFrameQueue();
}
void WebSocketChannel::processOutgoingFrameQueue()