Title: [138676] trunk/Source/WebCore
Revision
138676
Author
[email protected]
Date
2013-01-02 16:26:37 -0800 (Wed, 02 Jan 2013)

Log Message

        [WK2 NetworkProcess] Uploading fails if a client modified the request
        https://bugs.webkit.org/show_bug.cgi?id=105965

        Reviewed by Brady Eidson.

        Associating streams with additional information via a side HashMap does not work,
        because the stream we can see is an internal one, with address and other information
        not matching a stream that we created.

        It's surprising that this design issue was not causing major trouble without NetworkProcess.

        * platform/network/cf/FormDataStreamCFNet.cpp:
        (WebCore): Renamed FormContext to FormCreationContext, because this type only used
        for creation. Later, we use FormStreamFields as context.
        (WebCore::closeCurrentStream): Moved a star.
        (WebCore::formCreate): We no longer have a side map to keep updated.
        (WebCore::formFinalize): Ditto.
        (WebCore::formCopyProperty): Added an accessor to get FormData pointer from a stream.
        (WebCore::setHTTPBody): Ditto.
        (WebCore::httpBodyFromStream): Use the new property to get FormData pointer.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (138675 => 138676)


--- trunk/Source/WebCore/ChangeLog	2013-01-03 00:25:26 UTC (rev 138675)
+++ trunk/Source/WebCore/ChangeLog	2013-01-03 00:26:37 UTC (rev 138676)
@@ -1,3 +1,26 @@
+2013-01-02  Alexey Proskuryakov  <[email protected]>
+
+        [WK2 NetworkProcess] Uploading fails if a client modified the request
+        https://bugs.webkit.org/show_bug.cgi?id=105965
+
+        Reviewed by Brady Eidson.
+
+        Associating streams with additional information via a side HashMap does not work,
+        because the stream we can see is an internal one, with address and other information
+        not matching a stream that we created.
+
+        It's surprising that this design issue was not causing major trouble without NetworkProcess.
+
+        * platform/network/cf/FormDataStreamCFNet.cpp:
+        (WebCore): Renamed FormContext to FormCreationContext, because this type only used
+        for creation. Later, we use FormStreamFields as context.
+        (WebCore::closeCurrentStream): Moved a star.
+        (WebCore::formCreate): We no longer have a side map to keep updated.
+        (WebCore::formFinalize): Ditto.
+        (WebCore::formCopyProperty): Added an accessor to get FormData pointer from a stream.
+        (WebCore::setHTTPBody): Ditto.
+        (WebCore::httpBodyFromStream): Use the new property to get FormData pointer.
+
 2013-01-02  Elliott Sprehn  <[email protected]>
 
         Clean up dispatchEvent overrides and overloads

Modified: trunk/Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp (138675 => 138676)


--- trunk/Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp	2013-01-03 00:25:26 UTC (rev 138675)
+++ trunk/Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp	2013-01-03 00:26:37 UTC (rev 138676)
@@ -86,15 +86,11 @@
 
 namespace WebCore {
 
-static Mutex& streamFieldsMapMutex()
-{
-    DEFINE_STATIC_LOCAL(Mutex, staticMutex, ());
-    return staticMutex;
-}
-
 static void formEventCallback(CFReadStreamRef stream, CFStreamEventType type, void* context);
 
-struct FormContext {
+static CFStringRef formDataPointerPropertyName = CFSTR("WebKitFormDataPointer");
+
+struct FormCreationContext {
     RefPtr<FormData> formData;
     unsigned long long streamLength;
 };
@@ -113,15 +109,8 @@
     unsigned long long bytesSent;
 };
 
-typedef HashMap<CFReadStreamRef, FormStreamFields*> StreamFieldsMap;
-static StreamFieldsMap& streamFieldsMap()
+static void closeCurrentStream(FormStreamFields* form)
 {
-    DEFINE_STATIC_LOCAL(StreamFieldsMap, streamFieldsMap, ());
-    return streamFieldsMap;
-}
-
-static void closeCurrentStream(FormStreamFields *form)
-{
     if (form->currentStream) {
         CFReadStreamClose(form->currentStream);
         CFReadStreamSetClient(form->currentStream, kCFStreamEventNone, 0, 0);
@@ -205,7 +194,7 @@
 
 static void* formCreate(CFReadStreamRef stream, void* context)
 {
-    FormContext* formContext = static_cast<FormContext*>(context);
+    FormCreationContext* formContext = static_cast<FormCreationContext*>(context);
 
     FormStreamFields* newInfo = new FormStreamFields;
     newInfo->formData = formContext->formData.release();
@@ -224,10 +213,6 @@
     for (size_t i = 0; i < size; ++i)
         newInfo->remainingElements.append(newInfo->formData->elements()[size - i - 1]);
 
-    MutexLocker locker(streamFieldsMapMutex());
-    ASSERT(!streamFieldsMap().contains(stream));
-    streamFieldsMap().add(stream, newInfo);
-
     return newInfo;
 }
 
@@ -241,18 +226,8 @@
 static void formFinalize(CFReadStreamRef stream, void* context)
 {
     FormStreamFields* form = static_cast<FormStreamFields*>(context);
-
-    MutexLocker locker(streamFieldsMapMutex());
-
     ASSERT(form->formStream == stream);
-    ASSERT(streamFieldsMap().get(stream) == context);
 
-    // Do this right away because the CFReadStreamRef is being deallocated.
-    // We can't wait to remove this from the map until we finish finalizing
-    // on the main thread because in theory the freed memory could be reused
-    // for a new CFReadStream before that runs.
-    streamFieldsMap().remove(stream);
-
     callOnMainThread(formFinishFinalizationOnMainThread, form);
 }
 
@@ -327,6 +302,17 @@
     closeCurrentStream(form);
 }
 
+static CFTypeRef formCopyProperty(CFReadStreamRef, CFStringRef propertyName, void *context)
+{
+    FormStreamFields* form = static_cast<FormStreamFields*>(context);
+
+    if (kCFCompareEqualTo != CFStringCompare(propertyName, formDataPointerPropertyName, 0))
+        return 0;
+
+    long formDataAsNumber = static_cast<long>(reinterpret_cast<intptr_t>(form->formData.get()));
+    return CFNumberCreate(0, kCFNumberLongType, &formDataAsNumber);
+}
+
 static void formSchedule(CFReadStreamRef, CFRunLoopRef runLoop, CFStringRef runLoopMode, void* context)
 {
     FormStreamFields* form = static_cast<FormStreamFields*>(context);
@@ -426,9 +412,9 @@
     // Create and set the stream.
 
     // Pass the length along with the formData so it does not have to be recomputed.
-    FormContext formContext = { formData.release(), length };
+    FormCreationContext formContext = { formData.release(), length };
 
-    CFReadStreamCallBacksV1 callBacks = { 1, formCreate, formFinalize, 0, formOpen, 0, formRead, 0, formCanRead, formClose, 0, 0, 0, formSchedule, formUnschedule
+    CFReadStreamCallBacksV1 callBacks = { 1, formCreate, formFinalize, 0, formOpen, 0, formRead, 0, formCanRead, formClose, formCopyProperty, 0, 0, formSchedule, formUnschedule
     };
     RetainPtr<CFReadStreamRef> stream = adoptCF(CFReadStreamCreate(0, static_cast<const void*>(&callBacks), &formContext));
 
@@ -440,11 +426,20 @@
     if (!stream)
         return 0;
 
-    MutexLocker locker(streamFieldsMapMutex());
-    FormStreamFields* formStream = streamFieldsMap().get(stream);
-    if (!formStream)
+    // Passing the pointer as property appears to be the only way to associate a stream with FormData.
+    // A new stream is always created in CFURLRequestCopyHTTPRequestBodyStream (or -[NSURLRequest HTTPBodyStream]),
+    // so a side HashMap wouldn't work.
+    // Even the stream's context pointer is different from the one we returned from formCreate().
+
+    RetainPtr<CFNumberRef> formDataPointerAsCFNumber = adoptCF(static_cast<CFNumberRef>(CFReadStreamCopyProperty(stream, formDataPointerPropertyName)));
+    if (!formDataPointerAsCFNumber)
         return 0;
-    return formStream->formData.get();
+
+    long formDataPointerAsNumber;
+    if (!CFNumberGetValue(formDataPointerAsCFNumber.get(), kCFNumberLongType, &formDataPointerAsNumber))
+        return 0;
+
+    return reinterpret_cast<FormData*>(static_cast<intptr_t>(formDataPointerAsNumber));
 }
 
 PassRefPtr<FormData> httpBodyFromRequest(CFURLRequestRef request)
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to