From be5e7a982ba943ce43b7041c0216ae70f3fe524e Mon Sep 17 00:00:00 2001 From: Gregory Terzian <2792687+gterzian@users.noreply.github.com> Date: Thu, 14 Aug 2025 20:48:56 +0800 Subject: [PATCH] script: check if the canvas is paintable before measuring text (#38664) The `Canvas2dMsg::MeasureText` is dropped inside `send_canvas_2d_msg` if the canvas is not paintable, leading to a panic on the receiving end. Checking the paint-ability before sending the message prevents this panic, and if the canvas is not pain-table, a default text metrics is used. Testing: Manual testing of the minimal test case in the associated issue, and crash test added. Fixes: https://github.com/servo/servo/issues/36845 --------- Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com> --- components/script/canvas_state.rs | 22 +++++++++++++------ tests/wpt/meta/MANIFEST.json | 9 +++++++- .../text-metrics-for-unpaintable-crash.html | 6 +++++ 3 files changed, 29 insertions(+), 8 deletions(-) create mode 100644 tests/wpt/tests/html/canvas/text-metrics-for-unpaintable-crash.html diff --git a/components/script/canvas_state.rs b/components/script/canvas_state.rs index cd03a75d524..6bb83cfc863 100644 --- a/components/script/canvas_state.rs +++ b/components/script/canvas_state.rs @@ -1427,13 +1427,21 @@ impl CanvasState { self.set_font(canvas, CanvasContextState::DEFAULT_FONT_STYLE.into()); } - let (sender, receiver) = ipc::channel::().unwrap(); - self.send_canvas_2d_msg(Canvas2dMsg::MeasureText( - text.into(), - sender, - self.state.borrow().text_options(), - )); - let metrics = receiver.recv().unwrap(); + let metrics = { + if !self.is_paintable() { + CanvasTextMetrics::default() + } else { + let (sender, receiver) = ipc::channel::().unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::MeasureText( + text.into(), + sender, + self.state.borrow().text_options(), + )); + receiver + .recv() + .expect("Failed to receive response from canvas paint thread") + } + }; TextMetrics::new( global, diff --git a/tests/wpt/meta/MANIFEST.json b/tests/wpt/meta/MANIFEST.json index ebc587f7b93..4825ae0d957 100644 --- a/tests/wpt/meta/MANIFEST.json +++ b/tests/wpt/meta/MANIFEST.json @@ -8083,7 +8083,14 @@ {} ] ] - } + }, + "text-metrics-for-unpaintable-crash.html": [ + "5acecfd691acec60a155c1ec1ab571e0a8efb471", + [ + null, + {} + ] + ] }, "dom": { "elements": { diff --git a/tests/wpt/tests/html/canvas/text-metrics-for-unpaintable-crash.html b/tests/wpt/tests/html/canvas/text-metrics-for-unpaintable-crash.html new file mode 100644 index 00000000000..5acecfd691a --- /dev/null +++ b/tests/wpt/tests/html/canvas/text-metrics-for-unpaintable-crash.html @@ -0,0 +1,6 @@ + + + +