summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaymond Toy <rtoy@chromium.org>2020-01-24 18:04:19 +0000
committerMichael BrĂ¼ning <michael.bruning@qt.io>2020-03-24 08:17:01 +0000
commitf7524c757836473e2c8a87decef7bf24f41710eb (patch)
treed80e573e3f8cd1d7919789f537ecaa23c2a57f49
parent02e9407022a7e946eb8f2b4500d3316c85cdfa76 (diff)
downloadqtwebengine-chromium-f7524c757836473e2c8a87decef7bf24f41710eb.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: Michal Klocek <michal.klocek@qt.io>
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_array.h49
1 files changed, 18 insertions, 31 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 fc190a168ff..f7879c8a5bc 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_array.h
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_array.h
@@ -30,6 +30,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_AUDIO_ARRAY_H_
#include <string.h>
+#include "base/numerics/checked_math.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
@@ -62,45 +63,29 @@ class AudioArray {
unsigned initial_size = 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) || \
defined(WTF_USE_WEBAUDIO_OPENMAX_DL_FFT)
- const size_t kAlignment = 32;
+ const unsigned kAlignment = 32;
#else
- const size_t kAlignment = 16;
+ const unsigned kAlignment = 16;
#endif
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 size_t extra_allocation_bytes = 0;
-
- // Again, check for integer overflow.
- CHECK_GE(initial_size + extra_allocation_bytes, initial_size);
-
- T* allocation = static_cast<T*>(WTF::Partitions::FastMalloc(
- initial_size + extra_allocation_bytes,
- 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_ = n;
- is_allocation_good = true;
- Zero();
- } 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_; }
@@ -144,6 +129,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));