summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaymond Toy <rtoy@chromium.org>2021-03-02 15:15:29 +0000
committerMichael Brüning <michael.bruning@qt.io>2021-04-06 08:59:19 +0000
commita84e05c57d55130104fb1fa2d4aa5882e41a1fd1 (patch)
treeb7f614661b2e28b2e74a7c7df04ac9a1d8561773
parent1375de9dd256e6c5ec3d3dc5f2bccbf61d3ce95a (diff)
downloadqtwebengine-chromium-a84e05c57d55130104fb1fa2d4aa5882e41a1fd1.tar.gz
[Backport] CVE-2021-21160: Heap buffer overflow in WebAudio
Manual cherry-pick of patch originally reviewed on https://chromium-review.googlesource.com/c/chromium/src/+/2727697: Convert AudioParam NaN values to the default value If any output value of an AudioParam (including the intrinsic values and any inputs to the AudioParam), should be NaN, replace the NaN value with the associated defaultValue. This causes some slowdowns so SIMD/NEON code was added to mitigate the degradation. There is still some slowdown, but the worst case is now about 7% slower on x86 and 10% on arm. Generally, the slowdown is less than 2% and 5%, respectively. (Perversely, some results got faster, and the differences are statistically significant.) Full details can be found at https://docs.google.com/spreadsheets/d/1EhbLHm-9cUoEO5aj1vYemVBLQ3Dh4dCJPPLTfZPrZt4/edit?usp=sharing Manually tested the test case from the bug and the issue no longer occurs. (cherry picked from commit ab1862017b5717271a28376659944dddc602195c) (cherry picked from commit eb0c0353bf245885797d8ce0d1b864d88a381fbb) Bug: 1170531 Change-Id: I00d902b40a9ef9da990c6d68b664b1dcfc31b091 Commit-Queue: Raymond Toy <rtoy@chromium.org> Reviewed-by: Hongchan Choi <hongchan@chromium.org> Cr-Original-Original-Commit-Position: refs/heads/master@{#851733} Reviewed-by: Raymond Toy <rtoy@chromium.org> Cr-Original-Commit-Position: refs/branch-heads/4389@{#880} Cr-Original-Branched-From: 9251c5db2b6d5a59fe4eac7aafa5fed37c139bb7-refs/heads/master@{#843830} Reviewed-by: Victor-Gabriel Savu <vsavu@google.com> Commit-Queue: Artem Sumaneev <asumaneev@google.com> Cr-Commit-Position: refs/branch-heads/4240@{#1551} Cr-Branched-From: f297677702651916bbf65e59c0d4bbd4ce57d1ee-refs/heads/master@{#800218} Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io> Reviewed-by: Jüri Valdmann <juri.valdmann@qt.io>
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_param.cc63
1 files changed, 63 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_param.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_param.cc
index 2d596c59c27..6d945e3ca34 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_param.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_param.cc
@@ -25,10 +25,12 @@
#include "third_party/blink/renderer/modules/webaudio/audio_param.h"
+#include "build/build_config.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
+#include "third_party/blink/renderer/platform/audio/vector_math.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
@@ -227,6 +229,48 @@ void AudioParamHandler::CalculateSampleAccurateValues(
CalculateFinalValues(values, number_of_values, IsAudioRate());
}
+// Replace NaN values in |values| with |default_value|.
+static void HandleNaNValues(float* values,
+ unsigned number_of_values,
+ float default_value) {
+ unsigned k = 0;
+#if defined(ARCH_CPU_X86_FAMILY)
+ if (number_of_values >= 4) {
+ __m128 defaults = _mm_set1_ps(default_value);
+ for (k = 0; k < number_of_values; k += 4) {
+ __m128 v = _mm_loadu_ps(values + k);
+ // cmpuord returns all 1's if v is NaN for each elmeent of v.
+ __m128 isnan = _mm_cmpunord_ps(v, v);
+ // Replace NaN parts with default.
+ __m128 result = _mm_and_ps(isnan, defaults);
+ // Merge in the parts that aren't NaN
+ result = _mm_or_ps(_mm_andnot_ps(isnan, v), result);
+ _mm_storeu_ps(values + k, result);
+ }
+ }
+#elif defined(CPU_ARM_NEON)
+ if (number_of_values >= 4) {
+ uint32x4_t defaults = vreinterpretq_u32_f32(vdupq_n_f32(default_value));
+ for (k = 0; k < number_of_values; k += 4) {
+ float32x4_t v = vld1q_f32(values + k);
+ // Returns true (all ones) if v is not NaN
+ uint32x4_t is_not_nan = vceqq_f32(v, v);
+ // Get the parts that are not NaN
+ uint32x4_t result = vandq_u32(is_not_nan, vreinterpretq_u32_f32(v));
+ // Replace the parts that are NaN with the default and merge with previous
+ // result. (Note: vbic_u32(x, y) = x and not y)
+ result = vorrq_u32(result, vbicq_u32(defaults, is_not_nan));
+ vst1q_f32(values + k, vreinterpretq_f32_u32(result));
+ }
+ }
+#endif
+ for (; k < number_of_values; ++k) {
+ if (std::isnan(values[k])) {
+ values[k] = default_value;
+ }
+ }
+}
+
void AudioParamHandler::CalculateFinalValues(float* values,
unsigned number_of_values,
bool sample_accurate) {
@@ -276,6 +320,25 @@ void AudioParamHandler::CalculateFinalValues(float* values,
// Sum, with unity-gain.
summing_bus->SumFrom(*connection_bus);
}
+
+ float min_value = MinValue();
+ float max_value = MaxValue();
+
+ if (NumberOfRenderingConnections() > 0) {
+ // AudioParams by themselves don't produce NaN because of the finite min
+ // and max values. But an input to an AudioParam could have NaNs.
+ //
+ // NaN values in AudioParams must be replaced by the AudioParam's
+ // defaultValue. Then these values must be clamped to lie in the nominal
+ // range between the AudioParam's minValue and maxValue.
+ //
+ // See https://webaudio.github.io/web-audio-api/#computation-of-value.
+ HandleNaNValues(values, number_of_values, DefaultValue());
+ }
+
+ VectorMath::Vclip(values, 1, &min_value, &max_value, values, 1,
+ number_of_values);
+
}
void AudioParamHandler::CalculateTimelineValues(float* values,