aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrei Volykhin <andrei.volykhin@gmail.com>2025-04-17 09:41:23 +0300
committerGitHub <noreply@github.com>2025-04-17 06:41:23 +0000
commit95ee5708fa432a2903d39c40df5e38ff435f30c1 (patch)
tree0b15572f1c968fce70304cc2bd16e253cbb8bffb
parentd7e560c9c048a8ea3b9d5b4e4a8d3905d743c9d2 (diff)
downloadservo-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.rs25
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,