mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-10-20 06:59:47 +00:00
LibWeb/HTML: Avoid crash for extreme bitmap sizes in OffscreenCanvas
This commit is contained in:
parent
de3f32a5c9
commit
e3b5507113
Notes:
github-actions[bot]
2025-09-22 11:38:58 +00:00
Author: https://github.com/shannonbooth
Commit: e3b5507113
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6251
Reviewed-by: https://github.com/AtkinsSJ ✅
4 changed files with 51 additions and 5 deletions
|
@ -134,12 +134,18 @@ void OffscreenCanvas::reset_context_to_default_state()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void OffscreenCanvas::set_new_bitmap_size(Gfx::IntSize new_size)
|
WebIDL::ExceptionOr<void> OffscreenCanvas::set_new_bitmap_size(Gfx::IntSize new_size)
|
||||||
{
|
{
|
||||||
if (new_size.width() == 0 || new_size.height() == 0)
|
if (new_size.width() == 0 || new_size.height() == 0)
|
||||||
m_bitmap = nullptr;
|
m_bitmap = nullptr;
|
||||||
else {
|
else {
|
||||||
m_bitmap = MUST(Gfx::Bitmap::create(Gfx::BitmapFormat::RGBA8888, Gfx::IntSize { new_size.width(), new_size.height() }));
|
// FIXME: Other browsers appear to not throw for unreasonable sizes being set. We could consider deferring allocation of the bitmap until it is used,
|
||||||
|
// but for now, lets just allocate it here and throw if it fails instead of crashing.
|
||||||
|
auto bitmap_or_error = Gfx::Bitmap::create(Gfx::BitmapFormat::RGBA8888, Gfx::IntSize { new_size.width(), new_size.height() });
|
||||||
|
if (bitmap_or_error.is_error()) {
|
||||||
|
return WebIDL::InvalidStateError::create(realm(), Utf16String::formatted("Error in allocating bitmap: {}", bitmap_or_error.error()));
|
||||||
|
}
|
||||||
|
m_bitmap = bitmap_or_error.release_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_context.visit(
|
m_context.visit(
|
||||||
|
@ -155,7 +161,9 @@ void OffscreenCanvas::set_new_bitmap_size(Gfx::IntSize new_size)
|
||||||
[](Empty) {
|
[](Empty) {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
});
|
});
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<Gfx::Bitmap> OffscreenCanvas::bitmap() const
|
RefPtr<Gfx::Bitmap> OffscreenCanvas::bitmap() const
|
||||||
{
|
{
|
||||||
return m_bitmap;
|
return m_bitmap;
|
||||||
|
@ -166,7 +174,7 @@ WebIDL::ExceptionOr<void> OffscreenCanvas::set_width(WebIDL::UnsignedLong value)
|
||||||
Gfx::IntSize current_size = bitmap_size_for_canvas();
|
Gfx::IntSize current_size = bitmap_size_for_canvas();
|
||||||
current_size.set_width(value);
|
current_size.set_width(value);
|
||||||
|
|
||||||
set_new_bitmap_size(current_size);
|
TRY(set_new_bitmap_size(current_size));
|
||||||
reset_context_to_default_state();
|
reset_context_to_default_state();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -175,7 +183,7 @@ WebIDL::ExceptionOr<void> OffscreenCanvas::set_height(WebIDL::UnsignedLong value
|
||||||
Gfx::IntSize current_size = bitmap_size_for_canvas();
|
Gfx::IntSize current_size = bitmap_size_for_canvas();
|
||||||
current_size.set_height(value);
|
current_size.set_height(value);
|
||||||
|
|
||||||
set_new_bitmap_size(current_size);
|
TRY(set_new_bitmap_size(current_size));
|
||||||
reset_context_to_default_state();
|
reset_context_to_default_state();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ private:
|
||||||
JS::ThrowCompletionOr<HasOrCreatedContext> create_2d_context(JS::Value options);
|
JS::ThrowCompletionOr<HasOrCreatedContext> create_2d_context(JS::Value options);
|
||||||
|
|
||||||
void reset_context_to_default_state();
|
void reset_context_to_default_state();
|
||||||
void set_new_bitmap_size(Gfx::IntSize new_size);
|
WebIDL::ExceptionOr<void> set_new_bitmap_size(Gfx::IntSize new_size);
|
||||||
|
|
||||||
Variant<GC::Ref<HTML::OffscreenCanvasRenderingContext2D>, GC::Ref<WebGL::WebGLRenderingContext>, GC::Ref<WebGL::WebGL2RenderingContext>, Empty> m_context;
|
Variant<GC::Ref<HTML::OffscreenCanvasRenderingContext2D>, GC::Ref<WebGL::WebGLRenderingContext>, GC::Ref<WebGL::WebGL2RenderingContext>, Empty> m_context;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Fail
|
||||||
|
Fail OffscreenCanvas test: 2d.canvas.host.size.large
|
|
@ -0,0 +1,32 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>OffscreenCanvas test: 2d.canvas.host.size.large</title>
|
||||||
|
<script src="../../../../resources/testharness.js"></script>
|
||||||
|
<script src="../../../../resources/testharnessreport.js"></script>
|
||||||
|
<script src="../../../../html/canvas/resources/canvas-tests.js"></script>
|
||||||
|
|
||||||
|
<h1>2d.canvas.host.size.large</h1>
|
||||||
|
<p class="desc"></p>
|
||||||
|
|
||||||
|
<p class="notes">Not sure how reasonable this is, but the spec doesn't say there's an upper limit on the size.
|
||||||
|
<script>
|
||||||
|
var t = async_test("");
|
||||||
|
var t_pass = t.done.bind(t);
|
||||||
|
var t_fail = t.step_func(function(reason) {
|
||||||
|
throw reason;
|
||||||
|
});
|
||||||
|
t.step(function() {
|
||||||
|
|
||||||
|
var canvas = new OffscreenCanvas(100, 50);
|
||||||
|
var ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
|
var n = 2147483647; // 2^31 - 1, which should be supported by any sensible definition of "long"
|
||||||
|
canvas.width = n;
|
||||||
|
canvas.height = n;
|
||||||
|
_assertSame(canvas.width, n, "canvas.width", "n");
|
||||||
|
_assertSame(canvas.height, n, "canvas.height", "n");
|
||||||
|
t.done();
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
Loading…
Add table
Add a link
Reference in a new issue