Reluctantly tolerated by Darin Adler.
authorggaren <ggaren@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 29 Mar 2007 15:18:35 +0000 (15:18 +0000)
committerggaren <ggaren@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 29 Mar 2007 15:18:35 +0000 (15:18 +0000)
        Fixed <rdar://problem/5091330> REGRESSION: Repro crash in
        -[WebBaseNetscapePluginView(WebNPPCallbacks) destroyStream:reason:]
        navigating away from page with DivX movie plug-in (13203)

        The problem was that the DivX plug-in would ask us to destroy an NPStream
        that had already been destroyed, causing us to wander off into freed
        memory. (I believe the reason this was a regression was that we never used
        to destroy plug-in streams, period.)

        The solution here is to track the NPStreams belonging to a plug-in, and
        guard against plug-ins making calls with NPStreams that don't belong to
        them. (It turns out that NPN_DestroyStream is the only stream-based
        plug-in call we support.)

        (CarbonPathFromPOSIXPath): Fixed up a cast to be C++ compatible.
        * Plugins/WebBaseNetscapePluginView.mm:
        (-[WebBaseNetscapePluginView destroyStream:reason:]): The actual fix.
        Use helper method to guard against a plug-in using an NPStream that doesn't
        belong to it.
        * WebKit.xcodeproj/project.pbxproj: Made WebBaseNetscapePluginView ObjC++
        so I could use HashMap.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@20571 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebKit/ChangeLog
WebKit/Plugins/WebBaseNetscapePluginStream.h
WebKit/Plugins/WebBaseNetscapePluginStream.m
WebKit/Plugins/WebBaseNetscapePluginView.mm
WebKit/WebKit.xcodeproj/project.pbxproj

index 964bf29..a2f9e1b 100644 (file)
@@ -1,3 +1,29 @@
+2007-03-27  Geoffrey Garen  <ggaren@apple.com>
+
+        Reluctantly tolerated by Darin Adler.
+        
+        Fixed <rdar://problem/5091330> REGRESSION: Repro crash in 
+        -[WebBaseNetscapePluginView(WebNPPCallbacks) destroyStream:reason:] 
+        navigating away from page with DivX movie plug-in (13203)
+        
+        The problem was that the DivX plug-in would ask us to destroy an NPStream
+        that had already been destroyed, causing us to wander off into freed
+        memory. (I believe the reason this was a regression was that we never used 
+        to destroy plug-in streams, period.)
+        
+        The solution here is to track the NPStreams belonging to a plug-in, and 
+        guard against plug-ins making calls with NPStreams that don't belong to 
+        them. (It turns out that NPN_DestroyStream is the only stream-based 
+        plug-in call we support.)
+
+        (CarbonPathFromPOSIXPath): Fixed up a cast to be C++ compatible.
+        * Plugins/WebBaseNetscapePluginView.mm:
+        (-[WebBaseNetscapePluginView destroyStream:reason:]): The actual fix.
+        Use helper method to guard against a plug-in using an NPStream that doesn't
+        belong to it.
+        * WebKit.xcodeproj/project.pbxproj: Made WebBaseNetscapePluginView ObjC++
+        so I could use HashMap.
+
 2007-03-28  Adele Peterson  <adele@apple.com>
 
         Reviewed by Brady.
index bf6fa4e..8b1234e 100644 (file)
@@ -60,7 +60,9 @@
     NPP_URLNotifyProcPtr NPP_URLNotify;
 }
 
++ (NPP)ownerForStream:(WebBaseNetscapePluginStream *)stream;
 + (NPReason)reasonForError:(NSError *)error;
+
 - (NSError *)errorForReason:(NPReason)theReason;
 
 - (id)initWithRequestURL:(NSURL *)theRequestURL
index 53b7b8b..bc5dcb2 100644 (file)
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#import <WebKit/WebBaseNetscapePluginStream.h>
-
-#import <WebKit/WebBaseNetscapePluginView.h>
-#import <WebKit/WebKitErrorsPrivate.h>
-#import <WebKit/WebKitLogging.h>
-#import <WebKit/WebNetscapePluginPackage.h>
-#import <WebKit/WebNSObjectExtras.h>
-#import <WebKit/WebNSURLExtras.h>
-#import <WebKitSystemInterface.h>
-
+#import "WebBaseNetscapePluginStream.h"
+
+#import "WebBaseNetscapePluginView.h"
+#import "WebKitErrorsPrivate.h"
+#import "WebKitLogging.h"
+#import "WebNSObjectExtras.h"
+#import "WebNSURLExtras.h"
+#import "WebNetscapePluginPackage.h"
+#import <Foundation/NSURLResponse.h>
 #import <WebCore/WebCoreObjCExtras.h>
+#import <WebKitSystemInterface.h>
+#import <wtf/HashMap.h>
 
-#import <Foundation/NSURLResponse.h>
+#define WEB_REASON_NONE -1
 
 static char *CarbonPathFromPOSIXPath(const char *posixPath);
 
-#define WEB_REASON_NONE -1
+typedef HashMap<WebBaseNetscapePluginStream *, NPP> StreamMap;
+static StreamMap& streams()
+{
+    static StreamMap staticStreams;
+    return staticStreams;
+}
 
 @implementation WebBaseNetscapePluginStream
 
@@ -53,6 +59,11 @@ static char *CarbonPathFromPOSIXPath(const char *posixPath);
 }
 #endif
 
++ (NPP)ownerForStream:(WebBaseNetscapePluginStream *)stream
+{
+    return streams().get(stream);
+}
+
 + (NPReason)reasonForError:(NSError *)error
 {
     if (error == nil) {
@@ -105,6 +116,8 @@ static char *CarbonPathFromPOSIXPath(const char *posixPath);
     [self setPlugin:thePlugin];
     notifyData = theNotifyData;
     sendNotification = flag;
+
+    streams().add(self, thePlugin);
     
     isTerminated = NO;
     
@@ -129,6 +142,8 @@ static char *CarbonPathFromPOSIXPath(const char *posixPath);
     free((void *)stream.url);
     free(path);
 
+    streams().remove(self);
+
     [super dealloc];
 }
 
@@ -144,6 +159,8 @@ static char *CarbonPathFromPOSIXPath(const char *posixPath);
     free((void *)stream.url);
     free(path);
 
+    streams().remove(self);
+
     [super finalize];
 }
 
@@ -495,7 +512,7 @@ static char *CarbonPathFromPOSIXPath(const char *posixPath)
         CFRelease(url);
         if (hfsPath) {
             CFIndex bufSize = CFStringGetMaximumSizeOfFileSystemRepresentation(hfsPath);
-            char *filename = malloc(bufSize);
+            char* filename = static_cast<char*>(malloc(bufSize));
             CFStringGetFileSystemRepresentation(hfsPath, filename, bufSize);
             CFRelease(hfsPath);
             return filename;
index 4689af2..c255472 100644 (file)
@@ -2316,10 +2316,15 @@ static OSStatus TSMEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEve
 -(NPError)destroyStream:(NPStream*)stream reason:(NPReason)reason
 {
     LOG(Plugins, "NPN_DestroyStream");
-    if (!stream->ndata) {
+    WebBaseNetscapePluginStream *browserStream = static_cast<WebBaseNetscapePluginStream *>(stream->ndata);
+
+    // This function does a sanity check to ensure that the NPStream provided actually
+    // belongs to the plug-in that provided it, which fixes a crash in the DivX 
+    // plug-in: <rdar://problem/5093862> | http://bugs.webkit.org/show_bug.cgi?id=13203
+    if (!stream || [WebBaseNetscapePluginStream ownerForStream:browserStream] != plugin) {
+        LOG_ERROR("Invalid NPStream passed to NPN_DestroyStream: %p\n", stream);
         return NPERR_INVALID_INSTANCE_ERROR;
     }
-    WebBaseNetscapePluginStream *browserStream = (WebBaseNetscapePluginStream *)stream->ndata;
     [browserStream cancelLoadAndDestroyStreamWithError:[browserStream errorForReason:reason]];
     return NPERR_NO_ERROR;
 }
index aa00a0f..358a1ae 100644 (file)
                F59EAE410253C8DE018635CA /* WebCoreStatistics.mm */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCoreStatistics.mm; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                F5A55DC702BAA2E8018635CC /* WebHTMLRepresentationPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebHTMLRepresentationPrivate.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                F5A672B90263866E01000102 /* WebBaseNetscapePluginStream.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebBaseNetscapePluginStream.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
-               F5A672BA0263866E01000102 /* WebBaseNetscapePluginStream.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebBaseNetscapePluginStream.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
+               F5A672BA0263866E01000102 /* WebBaseNetscapePluginStream.m */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; indentWidth = 4; path = WebBaseNetscapePluginStream.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                F5AEBB3D024A527601C1A526 /* WebPreferences.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebPreferences.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                F5AFB45E02B94DC8018635CA /* WebFrameBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebFrameBridge.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                F5AFB45F02B94DC8018635CA /* WebFrameBridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebFrameBridge.mm; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };