diff options
author | Raymond Toy <rtoy@chromium.org> | 2020-01-24 18:04:19 +0000 |
---|---|---|
committer | Michael BrĂ¼ning <michael.bruning@qt.io> | 2020-03-02 12:25:41 +0000 |
commit | 5887eeff3a3f11be694eb3e94b6f3c211d1cb82f (patch) | |
tree | 61b5f0bab540057ec3167c2e42e0c06233db201e | |
parent | ca787f956d866ab1d72e9d2eba5a063404480a86 (diff) | |
download | qtwebengine-chromium-5887eeff3a3f11be694eb3e94b6f3c211d1cb82f.tar.gz |
[Backport] CVE-2020-6388 - Out of bounds memory access in WebAudio
Manual backport of patch originally reviewed on
https://chromium-review.googlesource.com/c/chromium/src/+/2011132:
Always allocate extra space for alignment of AudioArrays
Instead of trying an allocation to see if it's aligned, just always
allocate extra space for alignment. We waste a bit of space, but this
should not be huge. Arrays are typically at least 128 floats or more
(the render size), and we need 16-byte alignment so we'll only waste
3% worst case. This simplifies the algorithm too.
This means we don't need the static int that leads to data races.
(cherry picked from commit 7760babc3a1cf49af1f12bad772abfdab2dcbfd8)
Bug: 1042879
Change-Id: I8b820a207d13ebb0680c67bae60f4db2a45700b4
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
-rw-r--r-- | chromium/third_party/blink/renderer/platform/audio/audio_array.h | 41 |
1 files changed, 15 insertions, 26 deletions
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_array.h b/chromium/third_party/blink/renderer/platform/audio/audio_array.h index 7ff276e5b9e..0a8c263eb67 100644 --- a/chromium/third_party/blink/renderer/platform/audio/audio_array.h +++ b/chromium/third_party/blink/renderer/platform/audio/audio_array.h @@ -62,6 +62,8 @@ class AudioArray { CHECK_LE(n, std::numeric_limits<unsigned>::max() / sizeof(T)); uint32_t initial_size = static_cast<uint32_t>(sizeof(T) * n); + // Minimmum alignment requirements for arrays so that we can use + // SIMD. #if defined(ARCH_CPU_X86_FAMILY) || defined(WTF_USE_WEBAUDIO_FFMPEG) const unsigned kAlignment = 32; #else @@ -71,32 +73,17 @@ class AudioArray { if (allocation_) WTF::Partitions::FastFree(allocation_); - bool is_allocation_good = false; - - while (!is_allocation_good) { - // Initially we try to allocate the exact size, but if it's not aligned - // then we'll have to reallocate and from then on allocate extra. - static unsigned extra_allocation_bytes = 0; - - unsigned total = - base::CheckAdd(initial_size, extra_allocation_bytes).ValueOrDie(); - T* allocation = static_cast<T*>(WTF::Partitions::FastZeroedMalloc( - total, WTF_HEAP_PROFILER_TYPE_NAME(AudioArray<T>))); - CHECK(allocation); - - T* aligned_data = AlignedAddress(allocation, kAlignment); - - if (aligned_data == allocation || extra_allocation_bytes == kAlignment) { - allocation_ = allocation; - aligned_data_ = aligned_data; - size_ = static_cast<uint32_t>(n); - is_allocation_good = true; - } else { - // always allocate extra after the first alignment failure. - extra_allocation_bytes = kAlignment; - WTF::Partitions::FastFree(allocation); - } - } + // Always allocate extra space so that we are guaranteed to get + // the desired alignment. Some memory is wasted, but it should be + // small since most arrays are probably at least 128 floats (or + // doubles). + unsigned total = base::CheckAdd(initial_size, kAlignment).ValueOrDie(); + allocation_ = static_cast<T*>(WTF::Partitions::FastZeroedMalloc( + total, WTF_HEAP_PROFILER_TYPE_NAME(AudioArray<T>))); + CHECK(allocation_); + + aligned_data_ = AlignedAddress(allocation_, kAlignment); + size_ = static_cast<uint32_t>(n); } T* Data() { return aligned_data_; } @@ -140,6 +127,8 @@ class AudioArray { } private: + // Return an address that is aligned to an |alignment| boundary. + // |alignment| MUST be a power of two! static T* AlignedAddress(T* address, intptr_t alignment) { intptr_t value = reinterpret_cast<intptr_t>(address); return reinterpret_cast<T*>((value + alignment - 1) & ~(alignment - 1)); |