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 04765462da06902696458ea33558e9308e966f52..7ef076003605e2b6a148b865192544b68bc9265d 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 7eb1727ed83c4042d8c44a84a2aa958a5b3dc1a6..13a6ff219383d95ca5e565d95bece8374071eb3f 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 6aded8ffb3955b488d0f4f1e410610adc08c77dd..0b9747e13b9cd60848b471afc9a9a6e8d357e5d4 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 891126d5b55478fe1707182ddab5fd37dfa0816f..7d5f8587c8d64b4f761347f5f4ac14200f39dc5b 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 1af14df9c51b8bed7a2e08972aa8ed81584e480c..2e9f5afbcaf909413cdeeb65a5339fe7806e12cb 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 af5e3a286d6adc244a6eb6c5a4c652beb20a16bd..44353396d7071fa6ee17bb950c70bde94ce045e2 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)