diff options
author | Andrei Volykhin <andrei.volykhin@gmail.com> | 2025-04-17 09:41:23 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-04-17 06:41:23 +0000 |
commit | 95ee5708fa432a2903d39c40df5e38ff435f30c1 (patch) | |
tree | 0b15572f1c968fce70304cc2bd16e253cbb8bffb | |
parent | d7e560c9c048a8ea3b9d5b4e4a8d3905d743c9d2 (diff) | |
download | servo-95ee5708fa432a2903d39c40df5e38ff435f30c1.tar.gz servo-95ee5708fa432a2903d39c40df5e38ff435f30c1.zip |
imagedata: Fix overflow panic for too large ImageData (#36569)
In Servo debug build there are runtime crash due to "attempt to multiply
with overflow" panic
in case of creation too large ImageData (new ImageData(1<<31, 1<<31))
Use checked integer multiplication to catch occurred overflow
and throwing JS error (RangeError OR IndexSizeError).
--
- [x] ./mach build -d does not report any errors
- [x] ./mach test-tidy does not report any errors
- [x] There are tests for these changes
tests/wpt/tests/html/canvas/element/pixel-manipulation/2d.imageData.object.ctor.basics.html
Signed-off-by: Andrei Volykhin <andrei.volykhin@gmail.com>
-rw-r--r-- | components/script/dom/imagedata.rs | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/components/script/dom/imagedata.rs b/components/script/dom/imagedata.rs index d49d17d3bf9..bd45a80fce2 100644 --- a/components/script/dom/imagedata.rs +++ b/components/script/dom/imagedata.rs @@ -41,7 +41,15 @@ impl ImageData { mut data: Option<Vec<u8>>, can_gc: CanGc, ) -> Fallible<DomRoot<ImageData>> { - let len = width * height * 4; + // The color components of each pixel must be stored in four sequential + // elements in the order of red, green, blue, and then alpha. + let len = 4u32 + .checked_mul(width) + .and_then(|v| v.checked_mul(height)) + .ok_or(Error::Range( + "The requested image size exceeds the supported range".to_owned(), + ))?; + unsafe { let cx = GlobalScope::get_cx(); rooted!(in (*cx) let mut js_object = ptr::null_mut::<JSObject>()); @@ -119,8 +127,17 @@ impl ImageData { if width == 0 || height == 0 { return Err(Error::IndexSize); } + + // The color components of each pixel must be stored in four sequential + // elements in the order of red, green, blue, and then alpha. + // Please note when a too-large ImageData is created using a constructor + // historically throwns an IndexSizeError, instead of RangeError. + let len = 4u32 + .checked_mul(width) + .and_then(|v| v.checked_mul(height)) + .ok_or(Error::IndexSize)?; + let cx = GlobalScope::get_cx(); - let len = width * height * 4; let heap_typed_array = match new_initialized_heap_buffer_source::<ClampedU8>( HeapTypedArrayInit::Info { len, cx }, @@ -173,7 +190,7 @@ impl ImageData { } impl ImageDataMethods<crate::DomTypeHolder> for ImageData { - /// <https://html.spec.whatwg.org/multipage/#pixel-manipulation:dom-imagedata-3> + /// <https://html.spec.whatwg.org/multipage/#dom-imagedata> fn Constructor( global: &GlobalScope, proto: Option<HandleObject>, @@ -184,7 +201,7 @@ impl ImageDataMethods<crate::DomTypeHolder> for ImageData { Self::new_without_jsobject(global, proto, width, height, can_gc) } - /// <https://html.spec.whatwg.org/multipage/#pixel-manipulation:dom-imagedata-4> + /// <https://html.spec.whatwg.org/multipage/#dom-imagedata-with-data> fn Constructor_( _cx: JSContext, global: &GlobalScope, |