Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package webkit2gtk3 for openSUSE:Factory checked in at 2024-08-05 17:20:19 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/webkit2gtk3 (Old) and /work/SRC/openSUSE:Factory/.webkit2gtk3.new.7232 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "webkit2gtk3" Mon Aug 5 17:20:19 2024 rev:197 rq:1191197 version:2.44.2 Changes: -------- --- /work/SRC/openSUSE:Factory/webkit2gtk3/webkit2gtk3.changes 2024-07-05 19:44:13.463050337 +0200 +++ /work/SRC/openSUSE:Factory/.webkit2gtk3.new.7232/webkit2gtk3.changes 2024-08-05 17:20:21.968889100 +0200 @@ -1,0 +2,9 @@ +Thu Aug 1 20:25:14 UTC 2024 - Michael Gorse <mgo...@suse.com> + +- Add CVE fixes: + + webkit2gtk3-CVE-2024-40776.patch (boo#1228613 CVE-2024-40776) + + webkit2gtk3-CVE-2024-40779.patch (boo#1228693 CVE-2024-40779) + + webkit2gtk3-CVE-2024-40780.patch (boo#1228694 CVE-2024-40780) + + webkit2gtk3-CVE-2024-40782.patch (boo#1228695 CVE-2024-40782) + +------------------------------------------------------------------- New: ---- webkit2gtk3-CVE-2024-40776.patch webkit2gtk3-CVE-2024-40779.patch webkit2gtk3-CVE-2024-40780.patch webkit2gtk3-CVE-2024-40782.patch BETA DEBUG BEGIN: New:- Add CVE fixes: + webkit2gtk3-CVE-2024-40776.patch (boo#1228613 CVE-2024-40776) + webkit2gtk3-CVE-2024-40779.patch (boo#1228693 CVE-2024-40779) New: + webkit2gtk3-CVE-2024-40776.patch (boo#1228613 CVE-2024-40776) + webkit2gtk3-CVE-2024-40779.patch (boo#1228693 CVE-2024-40779) + webkit2gtk3-CVE-2024-40780.patch (boo#1228694 CVE-2024-40780) New: + webkit2gtk3-CVE-2024-40779.patch (boo#1228693 CVE-2024-40779) + webkit2gtk3-CVE-2024-40780.patch (boo#1228694 CVE-2024-40780) + webkit2gtk3-CVE-2024-40782.patch (boo#1228695 CVE-2024-40782) New: + webkit2gtk3-CVE-2024-40780.patch (boo#1228694 CVE-2024-40780) + webkit2gtk3-CVE-2024-40782.patch (boo#1228695 CVE-2024-40782) BETA DEBUG END: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ webkit2gtk3.spec ++++++ --- /var/tmp/diff_new_pack.B9nhLf/_old 2024-08-05 17:20:22.880926504 +0200 +++ /var/tmp/diff_new_pack.B9nhLf/_new 2024-08-05 17:20:22.880926504 +0200 @@ -93,6 +93,14 @@ Patch2: webkit2gtk3-disable-dmabuf-nvidia.patch # PATCH-FIX-UPSTREAM 9d5844679af8f84036f1b800307e799bd7ab73ba -- VA+DMABuf videos flicker Patch3: https://github.com/WebKit/WebKit/commit/9d5844679af8f84036f1b800307e799bd7ab73ba.patch +# PATCH-FIX-UPSTREAM webkit2gtk3-CVE-2024-40776.patch boo#1228613 mgo...@suse.com -- fix a use after free. +Patch4: webkit2gtk3-CVE-2024-40776.patch +# PATCH-FIX-UPSTREAM webkit2gtk3-CVE-2024-40779.patch boo#1228693 mgo...@suse.com -- fix a buffer overflow. +Patch5: webkit2gtk3-CVE-2024-40779.patch +# PATCH-FIX-UPSTREAM webkit2gtk3-CVE-2024-40780.patch boo#1228694 mgo...@suse.com -- fix an out-of-bounds read. +Patch6: webkit2gtk3-CVE-2024-40780.patch +# PATCH-FIX-UPSTREAM webkit2gtk3-CVE-2024-40782.patch boo#1228695 mgo...@suse.com -- fix a NULL pointer dereference. +Patch7: webkit2gtk3-CVE-2024-40782.patch BuildRequires: Mesa-libEGL-devel BuildRequires: Mesa-libGL-devel ++++++ webkit2gtk3-CVE-2024-40776.patch ++++++ >From b951404ea74ae432312a83138f5c8945a0d09e1b Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard <j...@apple.com> Date: Wed, 24 Apr 2024 19:01:06 -0700 Subject: [PATCH] Cherry-pick 272448.960@safari-7618-branch (b7ccdb65258e). https://bugs.webkit.org/show_bug.cgi?id=273176 Always copy all audio channels to the AudioBus to guarantee data lifetime. https://bugs.webkit.org/show_bug.cgi?id=273176 rdar://125166710 Reviewed by Chris Dumez. Following 275262@main, a task is dispatched on the audio render thread. This task dispatch takes a reference to the source and destination AudioBus however when a MultiChannelResampler is in use, the source AudioBus may contain a raw pointer to the resampled's AudioArray and the lifetime of this object may be shorter than the AudioBus. In 232182@main, a speed and memory optimisation was added by passed-in buffer as memory for the first channel in the AudioBus. We revert this change for now and copy all channels' data to the AudioBus. Added test. * LayoutTests/webaudio/crashtest/audioworklet-concurrent-resampler-crash-expected.txt: Added. * LayoutTests/webaudio/crashtest/audioworklet-concurrent-resampler-crash.html: Added. * Source/WebCore/platform/audio/MultiChannelResampler.cpp: (WebCore::MultiChannelResampler::MultiChannelResampler): (WebCore::MultiChannelResampler::provideInputForChannel): * Source/WebCore/platform/audio/MultiChannelResampler.h: Canonical link: https://commits.webkit.org/274313.332@webkitglib/2.44 --- ...et-concurrent-resampler-crash-expected.txt | 1 + ...dioworklet-concurrent-resampler-crash.html | 44 +++++++++++++++++++ .../platform/audio/MultiChannelResampler.cpp | 23 ++-------- .../platform/audio/MultiChannelResampler.h | 2 - 4 files changed, 48 insertions(+), 22 deletions(-) create mode 100644 LayoutTests/webaudio/crashtest/audioworklet-concurrent-resampler-crash-expected.txt create mode 100644 LayoutTests/webaudio/crashtest/audioworklet-concurrent-resampler-crash.html diff --git a/LayoutTests/webaudio/crashtest/audioworklet-concurrent-resampler-crash-expected.txt b/LayoutTests/webaudio/crashtest/audioworklet-concurrent-resampler-crash-expected.txt new file mode 100644 index 000000000000..654ddf7f17ef --- /dev/null +++ b/LayoutTests/webaudio/crashtest/audioworklet-concurrent-resampler-crash-expected.txt @@ -0,0 +1 @@ +This test passes if it does not crash. diff --git a/LayoutTests/webaudio/crashtest/audioworklet-concurrent-resampler-crash.html b/LayoutTests/webaudio/crashtest/audioworklet-concurrent-resampler-crash.html new file mode 100644 index 000000000000..b3ab181d4787 --- /dev/null +++ b/LayoutTests/webaudio/crashtest/audioworklet-concurrent-resampler-crash.html @@ -0,0 +1,44 @@ +<html> +<head> + <script> + let worklet_source = ` + class Processor extends AudioWorkletProcessor { + process(inputs, outputs, parameters) { + return true; + } + } + registerProcessor('P2', Processor); + `; + + let blob = new Blob([worklet_source], { type: 'application/javascript' }); + let worklet = URL.createObjectURL(blob); + + var ctx = new AudioContext({ sampleRate: 44100}); + const dest = ctx.destination; + dest.channelCountMode = "max"; + + async function main() { + await ctx.audioWorklet.addModule(worklet); + var script_processor = ctx.createScriptProcessor(); + script_processor.onaudioprocess = function() { + dest.channelCount = 1; + audio_worklet.disconnect(); + if (window.testRunner) + testRunner.notifyDone(); + } + var audio_worklet = new AudioWorkletNode(ctx, "P2"); + script_processor.connect(audio_worklet); + audio_worklet.connect(dest); + } + </script> +</head> +<body onload="main()"> + <p>This test passes if it does not crash.</p> + <script> + if (window.testRunner) { + testRunner.waitUntilDone(); + testRunner.dumpAsText(); + } + </script> +</body> +</html> diff --git a/Source/WebCore/platform/audio/MultiChannelResampler.cpp b/Source/WebCore/platform/audio/MultiChannelResampler.cpp index e5a0cfc10caa..c44df274cbbc 100644 --- a/Source/WebCore/platform/audio/MultiChannelResampler.cpp +++ b/Source/WebCore/platform/audio/MultiChannelResampler.cpp @@ -42,19 +42,8 @@ namespace WebCore { MultiChannelResampler::MultiChannelResampler(double scaleFactor, unsigned numberOfChannels, unsigned requestFrames, Function<void(AudioBus*, size_t framesToProcess)>&& provideInput) : m_numberOfChannels(numberOfChannels) , m_provideInput(WTFMove(provideInput)) - , m_multiChannelBus(AudioBus::create(numberOfChannels, requestFrames, false)) + , m_multiChannelBus(AudioBus::create(numberOfChannels, requestFrames)) { - // As an optimization, we will use the buffer passed to provideInputForChannel() as channel memory for the first channel so we - // only need to allocate memory if there is more than one channel. - if (numberOfChannels > 1) { - m_channelsMemory = Vector<std::unique_ptr<AudioFloatArray>>(numberOfChannels - 1, [&](size_t i) { - size_t channelIndex = i + 1; - auto floatArray = makeUnique<AudioFloatArray>(requestFrames); - m_multiChannelBus->setChannelMemory(channelIndex, floatArray->data(), requestFrames); - return floatArray; - }); - } - // Create each channel's resampler. m_kernels = Vector<std::unique_ptr<SincResampler>>(numberOfChannels, [&](size_t channelIndex) { return makeUnique<SincResampler>(scaleFactor, requestFrames, std::bind(&MultiChannelResampler::provideInputForChannel, this, std::placeholders::_1, std::placeholders::_2, channelIndex)); @@ -93,16 +82,10 @@ void MultiChannelResampler::process(AudioBus* destination, size_t framesToProces void MultiChannelResampler::provideInputForChannel(std::span<float> buffer, size_t framesToProcess, unsigned channelIndex) { ASSERT(channelIndex < m_multiChannelBus->numberOfChannels()); - ASSERT(framesToProcess == m_multiChannelBus->length()); + ASSERT(framesToProcess <= m_multiChannelBus->length()); - if (!channelIndex) { - // As an optimization, we use the provided buffer as memory for the first channel in the AudioBus. This avoids - // having to memcpy() for the first channel. - RELEASE_ASSERT(framesToProcess <= buffer.size()); - m_multiChannelBus->setChannelMemory(0, buffer.data(), framesToProcess); + if (!channelIndex) m_provideInput(m_multiChannelBus.get(), framesToProcess); - return; - } // Copy the channel data from what we received from m_multiChannelProvider. memcpySpan(buffer.subspan(0, framesToProcess), m_multiChannelBus->channel(channelIndex)->span().subspan(0, framesToProcess)); diff --git a/Source/WebCore/platform/audio/MultiChannelResampler.h b/Source/WebCore/platform/audio/MultiChannelResampler.h index 25d43100b71f..214ee06567ac 100644 --- a/Source/WebCore/platform/audio/MultiChannelResampler.h +++ b/Source/WebCore/platform/audio/MultiChannelResampler.h @@ -29,7 +29,6 @@ #ifndef MultiChannelResampler_h #define MultiChannelResampler_h -#include "AudioArray.h" #include <memory> #include <wtf/Function.h> #include <wtf/Vector.h> @@ -62,7 +61,6 @@ private: size_t m_outputFramesReady { 0 }; Function<void(AudioBus*, size_t framesToProcess)> m_provideInput; RefPtr<AudioBus> m_multiChannelBus; - Vector<std::unique_ptr<AudioFloatArray>> m_channelsMemory; }; } // namespace WebCore -- 2.45.2 ++++++ webkit2gtk3-CVE-2024-40779.patch ++++++ >From 2fe5ae29a5f6434ef456afe9673a4f400ec63848 Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard <j...@apple.com> Date: Fri, 14 Jun 2024 16:08:19 -0700 Subject: [PATCH] Cherry-pick 272448.1085@safari-7618.3.10-branch (ff52ff7cb64e). https://bugs.webkit.org/show_bug.cgi?id=275431 HeapBufferOverflow in computeSampleUsingLinearInterpolation https://bugs.webkit.org/show_bug.cgi?id=275431 rdar://125617812 Reviewed by Youenn Fablet. Add boundary check. This is a copy of blink code for that same function. https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/modules/webaudio/audio_buffer_source_handler.cc;l=336-341 * LayoutTests/webaudio/crashtest/audiobuffer-sourcenode-resampler-crash-expected.txt: Added. * LayoutTests/webaudio/crashtest/audiobuffer-sourcenode-resampler-crash.html: Added. * Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp: (WebCore::AudioBufferSourceNode::renderFromBuffer): Canonical link: https://commits.webkit.org/274313.347@webkitglib/2.44 --- ...er-sourcenode-resampler-crash-expected.txt | 1 + ...udiobuffer-sourcenode-resampler-crash.html | 25 +++++++++++++++++++ .../webaudio/AudioBufferSourceNode.cpp | 6 +++++ 3 files changed, 32 insertions(+) create mode 100644 LayoutTests/webaudio/crashtest/audiobuffer-sourcenode-resampler-crash-expected.txt create mode 100644 LayoutTests/webaudio/crashtest/audiobuffer-sourcenode-resampler-crash.html diff --git a/LayoutTests/webaudio/crashtest/audiobuffer-sourcenode-resampler-crash-expected.txt b/LayoutTests/webaudio/crashtest/audiobuffer-sourcenode-resampler-crash-expected.txt new file mode 100644 index 000000000000..654ddf7f17ef --- /dev/null +++ b/LayoutTests/webaudio/crashtest/audiobuffer-sourcenode-resampler-crash-expected.txt @@ -0,0 +1 @@ +This test passes if it does not crash. diff --git a/LayoutTests/webaudio/crashtest/audiobuffer-sourcenode-resampler-crash.html b/LayoutTests/webaudio/crashtest/audiobuffer-sourcenode-resampler-crash.html new file mode 100644 index 000000000000..5fb2dd8c8a5f --- /dev/null +++ b/LayoutTests/webaudio/crashtest/audiobuffer-sourcenode-resampler-crash.html @@ -0,0 +1,25 @@ +<html> +<head> + <script> + async function main() { + var ctx = new AudioContext(); + var src = new AudioBufferSourceNode(ctx); + src.buffer = ctx.createBuffer(1, 8192, 44100); + src.start(undefined, 0.5); + src.playbackRate.value = -1; + src.connect(ctx.destination, 0, 0); + if (window.testRunner) + testRunner.notifyDone(); + } + </script> +</head> +<body onload="main()"> + <p>This test passes if it does not crash.</p> + <script> + if (window.testRunner) { + testRunner.waitUntilDone(); + testRunner.dumpAsText(); + } + </script> +</body> +</html> diff --git a/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp b/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp index 298bd48cdff5..740b793e0ec5 100644 --- a/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp +++ b/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp @@ -350,6 +350,12 @@ bool AudioBufferSourceNode::renderFromBuffer(AudioBus* bus, unsigned destination if (readIndex2 >= maxFrame) readIndex2 = m_isLooping ? minFrame : readIndex; + // Final sanity check on buffer access. + // FIXME: as an optimization, try to get rid of this inner-loop check and + // put assertions and guards before the loop. + if (readIndex >= bufferLength || readIndex2 >= bufferLength) + break; + // Linear interpolation. for (unsigned i = 0; i < numberOfChannels; ++i) { float* destination = destinationChannels[i]; -- 2.45.2 ++++++ webkit2gtk3-CVE-2024-40780.patch ++++++ >From e83e4c7460972898dc06a5f5ab36eed7c6b101b5 Mon Sep 17 00:00:00 2001 From: Jer Noble <jer.no...@apple.com> Date: Tue, 11 Jun 2024 11:54:06 -0700 Subject: [PATCH] Cherry-pick 272448.1080@safari-7618.3.10-branch (64c9479d6f29). https://bugs.webkit.org/show_bug.cgi?id=275273 Add check in AudioBufferSourceNode::renderFromBuffer() when detune is set to large negative value https://bugs.webkit.org/show_bug.cgi?id=275273 rdar://125617842 Reviewed by Eric Carlson. * LayoutTests/webaudio/audiobuffersourcenode-detune-crash-expected.txt: Added. * LayoutTests/webaudio/audiobuffersourcenode-detune-crash.html: Added. * Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp: (WebCore::AudioBufferSourceNode::renderFromBuffer): Canonical link: https://commits.webkit.org/274313.345@webkitglib/2.44 --- ...buffersourcenode-detune-crash-expected.txt | 10 +++++++ .../audiobuffersourcenode-detune-crash.html | 30 +++++++++++++++++++ .../webaudio/AudioBufferSourceNode.cpp | 7 +++++ 3 files changed, 47 insertions(+) create mode 100644 LayoutTests/webaudio/audiobuffersourcenode-detune-crash-expected.txt create mode 100644 LayoutTests/webaudio/audiobuffersourcenode-detune-crash.html diff --git a/LayoutTests/webaudio/audiobuffersourcenode-detune-crash-expected.txt b/LayoutTests/webaudio/audiobuffersourcenode-detune-crash-expected.txt new file mode 100644 index 000000000000..914ba0b133c4 --- /dev/null +++ b/LayoutTests/webaudio/audiobuffersourcenode-detune-crash-expected.txt @@ -0,0 +1,10 @@ +Attempting to create a AudioBufferSourceNode with a large negative detune value should not crash. + +On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". + + +PASS Test passed because it did not crash. +PASS successfullyParsed is true + +TEST COMPLETE + diff --git a/LayoutTests/webaudio/audiobuffersourcenode-detune-crash.html b/LayoutTests/webaudio/audiobuffersourcenode-detune-crash.html new file mode 100644 index 000000000000..e8af579db9d2 --- /dev/null +++ b/LayoutTests/webaudio/audiobuffersourcenode-detune-crash.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html> + <head> + <script src="../resources/js-test-pre.js"></script> + <script src="resources/audio-testing.js"></script> + </head> + <body> + <script> + description("Attempting to create a AudioBufferSourceNode with a large negative detune value should not crash."); + + jsTestIsAsync = true; + + var context = new AudioContext(); + var src = context.createBufferSource(); + var buffer = context.createBuffer(1, 256, 44100); + src.buffer = buffer; + src.start(undefined, 1); + src.connect(context.listener.positionX, 0); + var panner = context.createPanner(); + src.detune.value = -0xffffff; + panner.connect(context.destination); + setTimeout(() => { + testPassed("Test passed because it did not crash."); + finishJSTest(); + }, 100); + </script> + + <script src="../resources/js-test-post.js"></script> + </body> +</html> diff --git a/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp b/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp index f86bffb9b507..298bd48cdff5 100644 --- a/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp +++ b/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp @@ -328,9 +328,16 @@ bool AudioBufferSourceNode::renderFromBuffer(AudioBus* bus, unsigned destination virtualReadIndex = readIndex; } else if (!pitchRate) { unsigned readIndex = static_cast<unsigned>(virtualReadIndex); + int deltaFrames = static_cast<int>(virtualDeltaFrames); + maxFrame = static_cast<unsigned>(virtualMaxFrame); + + if (readIndex >= maxFrame) + readIndex -= deltaFrames; for (unsigned i = 0; i < numberOfChannels; ++i) std::fill_n(destinationChannels[i] + writeIndex, framesToProcess, sourceChannels[i][readIndex]); + + virtualReadIndex = readIndex; } else if (reverse) { unsigned maxFrame = static_cast<unsigned>(virtualMaxFrame); unsigned minFrame = static_cast<unsigned>(floorf(virtualMinFrame)); -- 2.45.2 ++++++ webkit2gtk3-CVE-2024-40782.patch ++++++ >From 617f1c4c9c7f1525abc47967d4c7734fed3ff525 Mon Sep 17 00:00:00 2001 From: Antti Koivisto <an...@apple.com> Date: Mon, 20 May 2024 11:36:34 -0700 Subject: [PATCH] Cherry-pick 279005@main (c2f9092d3a8e). https://bugs.webkit.org/show_bug.cgi?id=268770 Nullptr crash due to `display:block ruby` and continuations https://bugs.webkit.org/show_bug.cgi?id=268770 rdar://121960530 Reviewed by Alan Baradlay. Continuations may end up splitting anonymous 'display:ruby' box inside block ruby. * LayoutTests/fast/ruby/ruby-block-continuation-crash-expected.txt: Added. * LayoutTests/fast/ruby/ruby-block-continuation-crash.html: Added. * Source/WebCore/rendering/updating/RenderTreeBuilderRuby.cpp: (WebCore::RenderTreeBuilder::Ruby::findOrCreateParentForStyleBasedRubyChild): Find the correct anonymous box from nested continuation structure. Canonical link: https://commits.webkit.org/279005@main Canonical link: https://commits.webkit.org/274313.286@webkitglib/2.44 --- .../ruby/ruby-block-continuation-crash-expected.txt | 3 +++ .../fast/ruby/ruby-block-continuation-crash.html | 9 +++++++++ .../rendering/updating/RenderTreeBuilderRuby.cpp | 13 ++++++++++--- 3 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 LayoutTests/fast/ruby/ruby-block-continuation-crash-expected.txt create mode 100644 LayoutTests/fast/ruby/ruby-block-continuation-crash.html diff --git a/LayoutTests/fast/ruby/ruby-block-continuation-crash-expected.txt b/LayoutTests/fast/ruby/ruby-block-continuation-crash-expected.txt new file mode 100644 index 000000000000..f85a15505104 --- /dev/null +++ b/LayoutTests/fast/ruby/ruby-block-continuation-crash-expected.txt @@ -0,0 +1,3 @@ +base with +forced +line break annotation This test passes if it doesn't crash. diff --git a/LayoutTests/fast/ruby/ruby-block-continuation-crash.html b/LayoutTests/fast/ruby/ruby-block-continuation-crash.html new file mode 100644 index 000000000000..3f762d4236ea --- /dev/null +++ b/LayoutTests/fast/ruby/ruby-block-continuation-crash.html @@ -0,0 +1,9 @@ +<script> +if (window.testRunner) + testRunner.dumpAsText(); +</script> +<ruby style="position: absolute"> + <rb><span>base with <div>forced</div> line break</span></rb> + <rt>annotation</rt> +</ruby> +This test passes if it doesn't crash. diff --git a/Source/WebCore/rendering/updating/RenderTreeBuilderRuby.cpp b/Source/WebCore/rendering/updating/RenderTreeBuilderRuby.cpp index 62d8b6803323..9f7634612822 100644 --- a/Source/WebCore/rendering/updating/RenderTreeBuilderRuby.cpp +++ b/Source/WebCore/rendering/updating/RenderTreeBuilderRuby.cpp @@ -271,10 +271,17 @@ RenderElement& RenderTreeBuilder::Ruby::findOrCreateParentForStyleBasedRubyChild if (!child.isRenderText() && child.style().display() == DisplayType::Ruby && parent.style().display() == DisplayType::RubyBlock) return parent; - if (parent.style().display() == DisplayType::RubyBlock && parent.firstChild()) { + if (parent.style().display() == DisplayType::RubyBlock) { // See if we have an anonymous ruby box already. - ASSERT(parent.firstChild()->style().display() == DisplayType::Ruby); - return downcast<RenderElement>(*parent.firstChild()); + // FIXME: It should be the immediate child but continuations can break this assumption. + for (CheckedPtr first = parent.firstChild(); first; first = first->firstChildSlow()) { + if (!first->isAnonymous()) { + ASSERT_NOT_REACHED(); + break; + } + if (first->style().display() == DisplayType::Ruby) + return downcast<RenderElement>(*first); + } } if (parent.style().display() != DisplayType::Ruby) { -- 2.45.2