REGRESSION(r122215) - CachedImage::likelyToBeUsedSoon crashes on accessing a deleted...
authorhclam@chromium.org <hclam@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 28 Sep 2012 23:58:22 +0000 (23:58 +0000)
committerhclam@chromium.org <hclam@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 28 Sep 2012 23:58:22 +0000 (23:58 +0000)
https://bugs.webkit.org/show_bug.cgi?id=97749

Reviewed by James Robinson.

.:

Added a manual test to demonstrate drag image and crashing.

* ManualTests/drag-image-no-crash.html: Added.

Source/WebCore:

All implementations of Clipboard set themselves as clients to CachedImage
through the JS API setDrageImage() but they do not detach during destruction.
This causes memory corruption when CachedImage tries to access a deleted client
when MemoryCache prunes and calls CachedImage::likelyToUsedSoon().

Manual test added: ManualTests/drag-image-no-crash.html

* platform/chromium/ClipboardChromium.cpp:
(WebCore::ClipboardChromium::~ClipboardChromium):
* platform/gtk/ClipboardGtk.cpp:
(WebCore::ClipboardGtk::~ClipboardGtk):
* platform/mac/ClipboardMac.mm:
(WebCore::ClipboardMac::~ClipboardMac):
* platform/win/ClipboardWin.cpp:
(WebCore::ClipboardWin::~ClipboardWin):

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

ChangeLog
ManualTests/drag-image-no-crash.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/platform/chromium/ClipboardChromium.cpp
Source/WebCore/platform/gtk/ClipboardGtk.cpp
Source/WebCore/platform/mac/ClipboardMac.mm
Source/WebCore/platform/win/ClipboardWin.cpp

index 0476546..7ef0760 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2012-09-28  Alpha Lam  <hclam@chromium.org>
+
+        REGRESSION(r122215) - CachedImage::likelyToBeUsedSoon crashes on accessing a deleted CachedImageClient
+        https://bugs.webkit.org/show_bug.cgi?id=97749
+
+        Reviewed by James Robinson.
+
+        Added a manual test to demonstrate drag image and crashing.
+
+        * ManualTests/drag-image-no-crash.html: Added.
+
 2012-09-27  Keishi Hattori  <keishi@webkit.org>
 
         SuggestionPicker should support rtl
diff --git a/ManualTests/drag-image-no-crash.html b/ManualTests/drag-image-no-crash.html
new file mode 100644 (file)
index 0000000..dad8c07
--- /dev/null
@@ -0,0 +1,87 @@
+<html>
+<body>
+<script>
+// This is a 10x10 24-bits RGB BMP image in white.
+var imageString =
+"Qk12AQAAAAAAADYAAAAoAAAACgAAAAoAAAABABgAAAAAAEABAAATCwAAEwsAAAAAAAAAAAAAAAAA" +
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
+"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
+
+// Raw image byets.
+var imageRaw = window.atob(imageString).split("");
+
+// 10x10x3 bytes are image data.
+var pixelBytes = 300;
+var beginByte = imageRaw.length - pixelBytes;
+
+function generateNewImage()
+{
+    // Add 1 to image data.
+    for (var i = beginByte; i < imageRaw.length; ++i) {
+        var c = imageRaw[i].charCodeAt(0);
+        if (c == 255) {
+            imageRaw[i] = String.fromCharCode(0);
+        } else {
+            imageRaw[i] = String.fromCharCode(c+1);
+            break;
+        }
+    }
+
+    var bmpImage = new Image();
+    bmpImage.src = "data:image/bmp;base64," + window.btoa(imageRaw.join(""));
+    return bmpImage;
+}
+
+var imageCount = 0;
+function addImage()
+{
+    if (imageCount >= 1000 * 1000)
+        return;
+    document.getElementById("imageCanvas").appendChild(generateNewImage());
+    window.setTimeout("addImage()", 1);
+}
+
+function runTest()
+{
+    document.getElementById("dragFrame").contentWindow.location.href =
+        "about:blank";
+    addImage();
+}
+</script>
+<p>To run this test:</p>
+<p>1. Drag this text 10 times:
+   <iframe id="dragFrame" width="50" height="30">.</iframe></p>
+<p>2. Click this <button onclick="runTest();">Start</button> button.</p>
+<p>3. Let it run for 5 minutes and browser shouldn't crash.</p>
+<div id="imageCanvas"></div>
+
+<script>
+// Write this content to the iframe.
+var content =
+    "<" + "body" + ">" +
+    "<" + "script" + ">" +
+    "function dragStartHandler()" +
+    "{" +
+    "    var img = new Image();" +
+    "    img.src = 'data:image/bmp;base64," + imageString + "';" +
+    "    event.dataTransfer.setDragImage(img, 10, 10);" +
+    "}" +
+    "</" + "script" + ">" +
+    "<span ondragstart='dragStartHandler()'" +
+    "      style='-webkit-user-select:none;" +
+    "             -webkit-user-drag: element;" +
+    "             position: absolute; top: 0; left: 0;" +
+    "             background-color: blue;'>HERE</span>" +
+    "</" + "body" + ">";
+
+var doc = document.getElementById("dragFrame");
+doc.contentDocument.open();
+doc.contentDocument.write(content);
+doc.contentDocument.close();
+</script>
+</body>
+</html>
index 7eb1727..13a6ff2 100644 (file)
@@ -1,3 +1,26 @@
+2012-09-27  Alpha Lam  <hclam@chromium.org>
+
+        REGRESSION(r122215) - CachedImage::likelyToBeUsedSoon crashes on accessing a deleted CachedImageClient
+        https://bugs.webkit.org/show_bug.cgi?id=97749
+
+        Reviewed by James Robinson.
+
+        All implementations of Clipboard set themselves as clients to CachedImage
+        through the JS API setDrageImage() but they do not detach during destruction.
+        This causes memory corruption when CachedImage tries to access a deleted client
+        when MemoryCache prunes and calls CachedImage::likelyToUsedSoon().
+
+        Manual test added: ManualTests/drag-image-no-crash.html
+
+        * platform/chromium/ClipboardChromium.cpp:
+        (WebCore::ClipboardChromium::~ClipboardChromium):
+        * platform/gtk/ClipboardGtk.cpp:
+        (WebCore::ClipboardGtk::~ClipboardGtk):
+        * platform/mac/ClipboardMac.mm:
+        (WebCore::ClipboardMac::~ClipboardMac):
+        * platform/win/ClipboardWin.cpp:
+        (WebCore::ClipboardWin::~ClipboardWin):
+
 2012-09-28  Anders Carlsson  <andersca@apple.com>
 
         Remove Instance::setDidExecuteFunction
index 6aded8f..0b9747e 100644 (file)
@@ -226,6 +226,8 @@ ClipboardChromium::ClipboardChromium(ClipboardType clipboardType,
 
 ClipboardChromium::~ClipboardChromium()
 {
+    if (m_dragImage)
+        m_dragImage->removeClient(this);
 }
 
 PassRefPtr<ClipboardChromium> ClipboardChromium::create(ClipboardType clipboardType,
index 891126d..7d5f858 100644 (file)
@@ -74,6 +74,8 @@ ClipboardGtk::ClipboardGtk(ClipboardAccessPolicy policy, PassRefPtr<DataObjectGt
 
 ClipboardGtk::~ClipboardGtk()
 {
+    if (m_dragImage)
+        m_dragImage->removeClient(this);
 }
 
 static ClipboardDataType dataObjectTypeFromHTMLClipboardType(const String& rawType)
index 1af14df..2e9f5af 100644 (file)
@@ -65,6 +65,8 @@ ClipboardMac::ClipboardMac(ClipboardType clipboardType, const String& pasteboard
 
 ClipboardMac::~ClipboardMac()
 {
+    if (m_dragImage)
+        m_dragImage->removeClient(this);
 }
 
 bool ClipboardMac::hasData()
index af5e3a2..4435339 100644 (file)
@@ -355,6 +355,8 @@ ClipboardWin::ClipboardWin(ClipboardType clipboardType, const DragDataMap& dataM
 
 ClipboardWin::~ClipboardWin()
 {
+    if (m_dragImage)
+        m_dragImage->removeClient(this);
 }
 
 static bool writeURL(WCDataObject *data, const KURL& url, String title, bool withPlainText, bool withHTML)