Title: [98694] trunk/Source/WebCore
Revision
98694
Author
yu...@chromium.org
Date
2011-10-27 22:39:15 -0700 (Thu, 27 Oct 2011)

Log Message

Race condition in SocketStreamHandleCFNet when PAC script is used
https://bugs.webkit.org/show_bug.cgi?id=70894

Reviewed by Alexey Proskuryakov.

Pass callback functions that call ref() or deref() as retain/release member
of CFStreamClientContext.

No new tests, as it is not possible to write a test with PAC script enabled.

* platform/network/cf/SocketStreamHandle.h:
* platform/network/cf/SocketStreamHandleCFNet.cpp:
(WebCore::SocketStreamHandle::scheduleStreams):
(WebCore::SocketStreamHandle::retainSocketStreamHandle):
(WebCore::SocketStreamHandle::releaseSocketStreamHandle):
(WebCore::SocketStreamHandle::pacExecutionCallbackMainThread):
This callback may be called after platformClose() is already called. We should
not create new streams in this case.
(WebCore::SocketStreamHandle::executePACFileURL):
(WebCore::SocketStreamHandle::readStreamCallback):
This manual ref/deref can be safely removed as m_readStream holds the reference.
(WebCore::SocketStreamHandle::writeStreamCallback):
Ditto.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (98693 => 98694)


--- trunk/Source/WebCore/ChangeLog	2011-10-28 05:39:13 UTC (rev 98693)
+++ trunk/Source/WebCore/ChangeLog	2011-10-28 05:39:15 UTC (rev 98694)
@@ -1,3 +1,29 @@
+2011-10-28  Yuta Kitamura  <yu...@chromium.org>
+
+        Race condition in SocketStreamHandleCFNet when PAC script is used
+        https://bugs.webkit.org/show_bug.cgi?id=70894
+
+        Reviewed by Alexey Proskuryakov.
+
+        Pass callback functions that call ref() or deref() as retain/release member
+        of CFStreamClientContext.
+
+        No new tests, as it is not possible to write a test with PAC script enabled.
+
+        * platform/network/cf/SocketStreamHandle.h:
+        * platform/network/cf/SocketStreamHandleCFNet.cpp:
+        (WebCore::SocketStreamHandle::scheduleStreams):
+        (WebCore::SocketStreamHandle::retainSocketStreamHandle):
+        (WebCore::SocketStreamHandle::releaseSocketStreamHandle):
+        (WebCore::SocketStreamHandle::pacExecutionCallbackMainThread):
+        This callback may be called after platformClose() is already called. We should
+        not create new streams in this case.
+        (WebCore::SocketStreamHandle::executePACFileURL):
+        (WebCore::SocketStreamHandle::readStreamCallback):
+        This manual ref/deref can be safely removed as m_readStream holds the reference.
+        (WebCore::SocketStreamHandle::writeStreamCallback):
+        Ditto.
+
 2011-10-27  Arthur Hsu  <arthur...@chromium.org>
 
         Reland patch ensure font load before calling Skia during printing

Modified: trunk/Source/WebCore/platform/network/cf/SocketStreamHandle.h (98693 => 98694)


--- trunk/Source/WebCore/platform/network/cf/SocketStreamHandle.h	2011-10-28 05:39:13 UTC (rev 98693)
+++ trunk/Source/WebCore/platform/network/cf/SocketStreamHandle.h	2011-10-28 05:39:15 UTC (rev 98694)
@@ -74,7 +74,9 @@
 
     void addCONNECTCredentials(CFHTTPMessageRef response);
 
-    static CFStringRef copyCFStreamDescription(void* );
+    static void* retainSocketStreamHandle(void*);
+    static void releaseSocketStreamHandle(void*);
+    static CFStringRef copyCFStreamDescription(void*);
     static void readStreamCallback(CFReadStreamRef, CFStreamEventType, void*);
     static void writeStreamCallback(CFWriteStreamRef, CFStreamEventType, void*);
 #if PLATFORM(WIN)

Modified: trunk/Source/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp (98693 => 98694)


--- trunk/Source/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp	2011-10-28 05:39:13 UTC (rev 98693)
+++ trunk/Source/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp	2011-10-28 05:39:15 UTC (rev 98694)
@@ -82,7 +82,7 @@
     ASSERT(m_readStream);
     ASSERT(m_writeStream);
 
-    CFStreamClientContext clientContext = { 0, this, 0, 0, copyCFStreamDescription };
+    CFStreamClientContext clientContext = { 0, this, retainSocketStreamHandle, releaseSocketStreamHandle, copyCFStreamDescription };
     // FIXME: Pass specific events we're interested in instead of -1.
     CFReadStreamSetClient(m_readStream.get(), static_cast<CFOptionFlags>(-1), readStreamCallback, &clientContext);
     CFWriteStreamSetClient(m_writeStream.get(), static_cast<CFOptionFlags>(-1), writeStreamCallback, &clientContext);
@@ -104,6 +104,19 @@
     m_connectingSubstate = WaitingForConnect;
 }
 
+void* SocketStreamHandle::retainSocketStreamHandle(void* info)
+{
+    SocketStreamHandle* handle = static_cast<SocketStreamHandle*>(info);
+    handle->ref();
+    return handle;
+}
+
+void SocketStreamHandle::releaseSocketStreamHandle(void* info)
+{
+    SocketStreamHandle* handle = static_cast<SocketStreamHandle*>(info);
+    handle->deref();
+}
+
 CFStringRef SocketStreamHandle::copyPACExecutionDescription(void*)
 {
     return CFSTR("WebSocket proxy PAC file execution");
@@ -128,6 +141,8 @@
     MainThreadPACCallbackInfo* info = static_cast<MainThreadPACCallbackInfo*>(invocation);
     ASSERT(info->handle->m_connectingSubstate == ExecutingPACFile);
     // This time, the array won't have PAC as a first entry.
+    if (info->handle->m_state != Connecting)
+        return;
     info->handle->chooseProxyFromArray(info->proxyList);
     info->handle->createStreams();
     info->handle->scheduleStreams();
@@ -136,7 +151,7 @@
 void SocketStreamHandle::executePACFileURL(CFURLRef pacFileURL)
 {
     // CFNetwork returns an empty proxy array for WebScoket schemes, so use m_httpsURL.
-    CFStreamClientContext clientContext = { 0, this, 0, 0, copyPACExecutionDescription };
+    CFStreamClientContext clientContext = { 0, this, retainSocketStreamHandle, releaseSocketStreamHandle, copyPACExecutionDescription };
     m_pacRunLoopSource.adoptCF(CFNetworkExecuteProxyAutoConfigurationURL(pacFileURL, m_httpsURL.get(), pacExecutionCallback, &clientContext));
 #if PLATFORM(WIN)
     CFRunLoopAddSource(loaderRunLoop(), m_pacRunLoopSource.get(), kCFRunLoopDefaultMode);
@@ -443,8 +458,6 @@
         if (m_connectingSubstate == WaitingForConnect) {
             m_connectingSubstate = Connected;
             m_state = Open;
-
-            RefPtr<SocketStreamHandle> protect(this); // The client can close the handle, potentially removing the last reference.
             m_client->didOpenSocketStream(this);
             if (m_state == Closed)
                 break;
@@ -502,8 +515,6 @@
         if (m_connectingSubstate == WaitingForConnect) {
             m_connectingSubstate = Connected;
             m_state = Open;
-
-            RefPtr<SocketStreamHandle> protect(this); // The client can close the handle, potentially removing the last reference.
             m_client->didOpenSocketStream(this);
             break;
         }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to