From c78501f2bd44db47fbd4d0c0eefc73794fce4dc5 Mon Sep 17 00:00:00 2001 From: relrelb Date: Sat, 24 Apr 2021 19:14:51 +0300 Subject: [PATCH] avm1: Fix panic in BitmapData.loadBitmap BitmapData.loadBitmap is not subject to the size limit. That is, it can load larger bitmaps than the BitmapData constructor. Fix panic for large bitmaps by not invoking the BitmapData constructor directly. This should also improve performance. Do the same for BitmapData.clone. --- core/src/avm1/globals/bitmap_data.rs | 52 +++++++++++++--------------- core/src/avm1/object/bitmap_data.rs | 6 +++- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/core/src/avm1/globals/bitmap_data.rs b/core/src/avm1/globals/bitmap_data.rs index 1a0533990..8ca1499db 100644 --- a/core/src/avm1/globals/bitmap_data.rs +++ b/core/src/avm1/globals/bitmap_data.rs @@ -368,27 +368,22 @@ pub fn clone<'gc>( ) -> Result, Error<'gc>> { if let Some(bitmap_data) = this.as_bitmap_data_object() { if !bitmap_data.disposed() { - let proto = activation.context.avm1.prototypes.bitmap_data_constructor; - let new_bitmap_data = proto.construct( - activation, - &[ - bitmap_data.bitmap_data().read().width().into(), - bitmap_data.bitmap_data().read().height().into(), - bitmap_data.bitmap_data().read().transparency().into(), - 0xFFFFFF.into(), - ], - )?; - let new_bitmap_data_object = new_bitmap_data - .coerce_to_object(activation) - .as_bitmap_data_object() - .unwrap(); + let prototype = activation.context.avm1.prototypes.bitmap_data; + let new_bitmap_data = prototype.create_bare_object(activation, prototype)?; - new_bitmap_data_object + new_bitmap_data + .as_bitmap_data_object() + .unwrap() .bitmap_data() .write(activation.context.gc_context) - .set_pixels(bitmap_data.bitmap_data().read().pixels().to_vec()); + .set_pixels( + bitmap_data.bitmap_data().read().width(), + bitmap_data.bitmap_data().read().height(), + bitmap_data.bitmap_data().read().transparency(), + bitmap_data.bitmap_data().read().pixels().to_vec(), + ); - return Ok(new_bitmap_data); + return Ok(new_bitmap_data.into()); } } @@ -1305,22 +1300,23 @@ pub fn load_bitmap<'gc>( if let Some(Character::Bitmap(bitmap_object)) = character { if let Some(bitmap) = renderer.get_bitmap_pixels(bitmap_object.bitmap_handle()) { - let proto = activation.context.avm1.prototypes.bitmap_data_constructor; - let new_bitmap = - proto.construct(activation, &[bitmap.width.into(), bitmap.height.into()])?; - let new_bitmap_object = new_bitmap - .coerce_to_object(activation) - .as_bitmap_data_object() - .unwrap(); + let prototype = activation.context.avm1.prototypes.bitmap_data; + let new_bitmap_data = prototype.create_bare_object(activation, prototype)?; let pixels: Vec = bitmap.data.into(); - - new_bitmap_object + new_bitmap_data + .as_bitmap_data_object() + .unwrap() .bitmap_data() .write(activation.context.gc_context) - .set_pixels(pixels.into_iter().map(|p| p.into()).collect()); + .set_pixels( + bitmap.width, + bitmap.height, + true, + pixels.into_iter().map(|p| p.into()).collect(), + ); - return Ok(new_bitmap); + return Ok(new_bitmap_data.into()); } } diff --git a/core/src/avm1/object/bitmap_data.rs b/core/src/avm1/object/bitmap_data.rs index d45fe88da..a50abef85 100644 --- a/core/src/avm1/object/bitmap_data.rs +++ b/core/src/avm1/object/bitmap_data.rs @@ -215,8 +215,12 @@ impl BitmapData { &self.pixels } - pub fn set_pixels(&mut self, pixels: Vec) { + pub fn set_pixels(&mut self, width: u32, height: u32, transparency: bool, pixels: Vec) { + self.width = width; + self.height = height; + self.transparency = transparency; self.pixels = pixels; + self.dirty = true; } pub fn pixels_rgba(&self) -> Vec {