Title: [152116] tags/Safari-537.47

Diff

Modified: tags/Safari-537.47/LayoutTests/ChangeLog (152115 => 152116)


--- tags/Safari-537.47/LayoutTests/ChangeLog	2013-06-27 18:01:43 UTC (rev 152115)
+++ tags/Safari-537.47/LayoutTests/ChangeLog	2013-06-27 18:08:52 UTC (rev 152116)
@@ -1,5 +1,19 @@
 2013-06-27  Lucas Forschler  <lforsch...@apple.com>
 
+        Merge r152038
+
+    2013-06-26  Jer Noble  <jer.no...@apple.com>
+
+            Potential use-after-free after neutering AudioBuffer's underlying ArrayBuffer.
+            https://bugs.webkit.org/show_bug.cgi?id=118040
+
+            Reviewed by Filip Pizlo.
+
+            * webaudio/audiobuffer-neuter.html: Added.
+            * webaudio/audiobuffer-neuter-expected.txt: Added.
+
+2013-06-27  Lucas Forschler  <lforsch...@apple.com>
+
         Merge r151868
 
     2013-06-21  Brent Fulgham  <bfulg...@apple.com>

Copied: tags/Safari-537.47/LayoutTests/webaudio/audiobuffer-neuter-expected.txt (from rev 152038, trunk/LayoutTests/webaudio/audiobuffer-neuter-expected.txt) (0 => 152116)


--- tags/Safari-537.47/LayoutTests/webaudio/audiobuffer-neuter-expected.txt	                        (rev 0)
+++ tags/Safari-537.47/LayoutTests/webaudio/audiobuffer-neuter-expected.txt	2013-06-27 18:08:52 UTC (rev 152116)
@@ -0,0 +1,3 @@
+Tests that neutered AudioBuffers do not produce garbage
+PASS Output matches expectations.
+

Copied: tags/Safari-537.47/LayoutTests/webaudio/audiobuffer-neuter.html (from rev 152038, trunk/LayoutTests/webaudio/audiobuffer-neuter.html) (0 => 152116)


--- tags/Safari-537.47/LayoutTests/webaudio/audiobuffer-neuter.html	                        (rev 0)
+++ tags/Safari-537.47/LayoutTests/webaudio/audiobuffer-neuter.html	2013-06-27 18:08:52 UTC (rev 152116)
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<head>
+    <script src=""
+    <script src=""
+    <script src=""
+    <script>
+        var sampleRate = 44100.0;
+        var lengthInSeconds = 0.1;
+        var context;
+        var source;
+        var sourceBuffer;
+
+        function runTest()
+        {
+            if (window.testRunner) {
+                testRunner.dumpAsText();
+                testRunner.waitUntilDone();
+            }
+
+            var numberOfFrames = sampleRate * lengthInSeconds;
+            context = new webkitOfflineAudioContext(1, numberOfFrames, sampleRate);
+            sourceBuffer = createConstantBuffer(context, numberOfFrames, 0.5);
+            var data = ""
+
+            var string = [
+                "_onmessage_ = function(e) {",
+                "   var view = new Float32Array(e.data)",
+                "   for (var i=0; i < view.length; i++)",
+                "       view[i] = 100;",
+                "    postMessage('done');",
+                "};"
+            ].join('\n');
+            var blobURL = URL.createObjectURL(new Blob([string]));
+
+            var worker = new Worker(blobURL);
+            worker._onmessage_ = workerReply;
+            worker.postMessage(data, [data]);
+        }
+
+        function workerReply(event) {
+            source = context.createBufferSource();
+            source.buffer = sourceBuffer;
+            source.connect(context.destination);
+            source.start(0);
+            context._oncomplete_ = finishTest;
+            context.startRendering();
+        }
+
+        function finishTest(event) {
+            var renderedBuffer = event.renderedBuffer;
+            var numberOfFrames = sampleRate * lengthInSeconds;
+            var expectedBuffer = createConstantBuffer(context, numberOfFrames, 0.5);
+
+            var renderedData = renderedBuffer.getChannelData(0);
+            var expectedData = expectedBuffer.getChannelData(0);
+
+            for (var i = 0; i < numberOfFrames; ++i) {
+                if (expectedData[i] != renderedData[i]) {
+                    testFailed('expected: ' + expectedData[i] + ' actual: ' + renderedData[i]);
+                    finishJSTest();
+                    if (window.testRunner)
+                        testRunner.notifyDone();
+                }
+            }
+
+            testPassed('Output matches expectations.');
+            finishJSTest();
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }
+
+    </script>
+</head>
+<body _onload_="runTest()">
+    <div>Tests that neutered AudioBuffers do not produce garbage</div>
+    <div id="console"></div>
+</body>
+
+

Modified: tags/Safari-537.47/Source/WTF/ChangeLog (152115 => 152116)


--- tags/Safari-537.47/Source/WTF/ChangeLog	2013-06-27 18:01:43 UTC (rev 152115)
+++ tags/Safari-537.47/Source/WTF/ChangeLog	2013-06-27 18:08:52 UTC (rev 152116)
@@ -1,5 +1,31 @@
 2013-06-27  Lucas Forschler  <lforsch...@apple.com>
 
+        Merge r152038
+
+    2013-06-26  Jer Noble  <jer.no...@apple.com>
+
+            Potential use-after-free after neutering AudioBuffer's underlying ArrayBuffer.
+            https://bugs.webkit.org/show_bug.cgi?id=118040
+
+            Reviewed by Filip Pizlo.
+
+            Add support for 'unneuterable' ArrayBufferViews. Views marked as such will have their underlying
+            ArrayBuffer objects copied rather than transferred to a new view.
+
+            * wtf/ArrayBuffer.cpp:
+            (WTF::ArrayBuffer::transfer): Check whether the associated views are neuterable, and if not
+                    clone the ArrayBuffer rather than transferring it.
+            * wtf/ArrayBuffer.h:
+            (WTF::ArrayBufferContents::copyTo): Added. Utility function.
+            * wtf/ArrayBufferView.cpp:
+            (WTF::ArrayBufferView::ArrayBufferView):
+            (WTF::ArrayBufferView::neuter):
+            * wtf/ArrayBufferView.h:
+            (WTF::ArrayBufferView::setNeuterable):
+            (WTF::ArrayBufferView::isNeuterable):
+
+2013-06-27  Lucas Forschler  <lforsch...@apple.com>
+
         Merge r152035
 
     2013-06-26  Brent Fulgham  <bfulg...@apple.com>

Modified: tags/Safari-537.47/Source/WTF/wtf/ArrayBuffer.cpp (152115 => 152116)


--- tags/Safari-537.47/Source/WTF/wtf/ArrayBuffer.cpp	2013-06-27 18:01:43 UTC (rev 152115)
+++ tags/Safari-537.47/Source/WTF/wtf/ArrayBuffer.cpp	2013-06-27 18:08:52 UTC (rev 152116)
@@ -42,12 +42,25 @@
         return false;
     }
 
-    m_contents.transfer(result);
+    bool allViewsAreNeuterable = true;
+    for (ArrayBufferView* i = m_firstView; i; i = i->m_nextView) {
+        if (!i->isNeuterable())
+            allViewsAreNeuterable = false;
+    }
 
+    if (allViewsAreNeuterable)
+        m_contents.transfer(result);
+    else {
+        m_contents.copyTo(result);
+        if (!result.m_data)
+            return false;
+    }
+
     while (m_firstView) {
         ArrayBufferView* current = m_firstView;
         removeView(current);
-        current->neuter();
+        if (allViewsAreNeuterable || current->isNeuterable())
+            current->neuter();
         neuteredViews.append(current);
     }
     return true;

Modified: tags/Safari-537.47/Source/WTF/wtf/ArrayBuffer.h (152115 => 152116)


--- tags/Safari-537.47/Source/WTF/wtf/ArrayBuffer.h	2013-06-27 18:01:43 UTC (rev 152115)
+++ tags/Safari-537.47/Source/WTF/wtf/ArrayBuffer.h	2013-06-27 18:08:52 UTC (rev 152116)
@@ -72,6 +72,16 @@
         m_sizeInBytes = 0;
     }
 
+    void copyTo(ArrayBufferContents& other)
+    {
+        ASSERT(!other.m_data);
+        ArrayBufferContents::tryAllocate(m_sizeInBytes, sizeof(char), ArrayBufferContents::DontInitialize, other);
+        if (!other.m_data)
+            return;
+        memcpy(other.m_data, m_data, m_sizeInBytes);
+        other.m_sizeInBytes = m_sizeInBytes;
+    }
+
     void* m_data;
     unsigned m_sizeInBytes;
 };

Modified: tags/Safari-537.47/Source/WTF/wtf/ArrayBufferView.cpp (152115 => 152116)


--- tags/Safari-537.47/Source/WTF/wtf/ArrayBufferView.cpp	2013-06-27 18:01:43 UTC (rev 152115)
+++ tags/Safari-537.47/Source/WTF/wtf/ArrayBufferView.cpp	2013-06-27 18:08:52 UTC (rev 152116)
@@ -33,6 +33,7 @@
 ArrayBufferView::ArrayBufferView(PassRefPtr<ArrayBuffer> buffer,
                        unsigned byteOffset)
         : m_byteOffset(byteOffset)
+        , m_isNeuterable(true)
         , m_buffer(buffer)
         , m_prevView(0)
         , m_nextView(0)

Modified: tags/Safari-537.47/Source/WTF/wtf/ArrayBufferView.h (152115 => 152116)


--- tags/Safari-537.47/Source/WTF/wtf/ArrayBufferView.h	2013-06-27 18:01:43 UTC (rev 152115)
+++ tags/Safari-537.47/Source/WTF/wtf/ArrayBufferView.h	2013-06-27 18:08:52 UTC (rev 152116)
@@ -69,6 +69,9 @@
 
     virtual unsigned byteLength() const = 0;
 
+    void setNeuterable(bool flag) { m_isNeuterable = flag; }
+    bool isNeuterable() const { return m_isNeuterable; }
+
     WTF_EXPORT_PRIVATE virtual ~ArrayBufferView();
 
   protected:
@@ -127,7 +130,8 @@
     // This is the address of the ArrayBuffer's storage, plus the byte offset.
     void* m_baseAddress;
 
-    unsigned m_byteOffset;
+    unsigned m_byteOffset : 31;
+    bool m_isNeuterable : 1;
 
   private:
     friend class ArrayBuffer;

Modified: tags/Safari-537.47/Source/WebCore/ChangeLog (152115 => 152116)


--- tags/Safari-537.47/Source/WebCore/ChangeLog	2013-06-27 18:01:43 UTC (rev 152115)
+++ tags/Safari-537.47/Source/WebCore/ChangeLog	2013-06-27 18:08:52 UTC (rev 152116)
@@ -1,5 +1,31 @@
 2013-06-27  Lucas Forschler  <lforsch...@apple.com>
 
+        Merge r152038
+
+    2013-06-26  Jer Noble  <jer.no...@apple.com>
+
+            Potential use-after-free after neutering AudioBuffer's underlying ArrayBuffer.
+            https://bugs.webkit.org/show_bug.cgi?id=118040
+
+            Reviewed by Filip Pizlo.
+
+            Test: webaudio/audiobuffer-neuter.html
+
+            When creating an AudioBuffer's backing ArrayBufferView objects, mark them as 'unneuterable',
+            meaning the underlying data will be copied in a neuter scenario rather than transferred. This
+            means the underlying assumtions of the webaudio code can continue to assume that the memory
+            areas owned by the ArrayBufferView will be present until the AudioBuffer is itself destroyed.
+
+            In order to not expose the 'unneuterable' behavior to _javascript_, return a fresh Float32Array
+            wrapper around the ArrayBuffer object, rather than our own.
+
+            * Modules/webaudio/AudioBuffer.cpp:
+            (WebCore::AudioBuffer::AudioBuffer): Mark the newly created channels as not neuterable.
+            (WebCore::AudioBuffer::getChannelData): Return a new Float32Array object rather than a pointer to our own.
+            * Modules/webaudio/AudioBuffer.h:
+
+2013-06-27  Lucas Forschler  <lforsch...@apple.com>
+
         Merge r152035
 
     2013-06-26  Brent Fulgham  <bfulg...@apple.com>

Modified: tags/Safari-537.47/Source/WebCore/Modules/webaudio/AudioBuffer.cpp (152115 => 152116)


--- tags/Safari-537.47/Source/WebCore/Modules/webaudio/AudioBuffer.cpp	2013-06-27 18:01:43 UTC (rev 152115)
+++ tags/Safari-537.47/Source/WebCore/Modules/webaudio/AudioBuffer.cpp	2013-06-27 18:08:52 UTC (rev 152116)
@@ -36,6 +36,7 @@
 #include "AudioContext.h"
 #include "AudioFileReader.h"
 #include "ExceptionCode.h"
+#include "ExceptionCodePlaceholder.h"
 
 namespace WebCore {
 
@@ -65,6 +66,7 @@
 
     for (unsigned i = 0; i < numberOfChannels; ++i) {
         RefPtr<Float32Array> channelDataArray = Float32Array::create(m_length);
+        channelDataArray->setNeuterable(false);
         m_channels.append(channelDataArray);
     }
 }
@@ -79,6 +81,7 @@
     m_channels.reserveCapacity(numberOfChannels);
     for (unsigned i = 0; i < numberOfChannels; ++i) {
         RefPtr<Float32Array> channelDataArray = Float32Array::create(m_length);
+        channelDataArray->setNeuterable(false);
         channelDataArray->setRange(bus->channel(i)->data(), m_length, 0);
         m_channels.append(channelDataArray);
     }
@@ -89,14 +92,15 @@
     m_channels.clear();
 }
 
-Float32Array* AudioBuffer::getChannelData(unsigned channelIndex, ExceptionCode& ec)
+PassRefPtr<Float32Array> AudioBuffer::getChannelData(unsigned channelIndex, ExceptionCode& ec)
 {
     if (channelIndex >= m_channels.size()) {
         ec = SYNTAX_ERR;
         return 0;
     }
 
-    return m_channels[channelIndex].get();
+    Float32Array* channelData = m_channels[channelIndex].get();
+    return Float32Array::create(channelData->buffer(), channelData->byteOffset(), channelData->length());
 }
 
 Float32Array* AudioBuffer::getChannelData(unsigned channelIndex)

Modified: tags/Safari-537.47/Source/WebCore/Modules/webaudio/AudioBuffer.h (152115 => 152116)


--- tags/Safari-537.47/Source/WebCore/Modules/webaudio/AudioBuffer.h	2013-06-27 18:01:43 UTC (rev 152115)
+++ tags/Safari-537.47/Source/WebCore/Modules/webaudio/AudioBuffer.h	2013-06-27 18:08:52 UTC (rev 152116)
@@ -55,7 +55,7 @@
 
     // Channel data access
     unsigned numberOfChannels() const { return m_channels.size(); }
-    Float32Array* getChannelData(unsigned channelIndex, ExceptionCode&);
+    PassRefPtr<Float32Array> getChannelData(unsigned channelIndex, ExceptionCode&);
     Float32Array* getChannelData(unsigned channelIndex);
     void zero();
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to