diff --git a/core/src/avm2.rs b/core/src/avm2.rs index 6dbdd7d41..fc744979b 100644 --- a/core/src/avm2.rs +++ b/core/src/avm2.rs @@ -9,7 +9,6 @@ use crate::context::UpdateContext; use crate::string::AvmString; use fnv::FnvHashMap; use gc_arena::{Collect, GcCell, MutationContext}; -use std::rc::Rc; use swf::avm2::read::Reader; use swf::{DoAbc, DoAbcFlag}; @@ -287,19 +286,28 @@ impl<'gc> Avm2<'gc> { do_abc: DoAbc, domain: Domain<'gc>, ) -> Result<(), Error<'gc>> { - let mut read = Reader::new(do_abc.data); + let mut reader = Reader::new(do_abc.data); + let abc = match reader.read() { + Ok(abc) => abc, + Err(_) => { + let mut activation = Activation::from_nothing(context.reborrow()); + return Err(Error::AvmError(crate::avm2::error::verify_error( + &mut activation, + "Error #1107: The ABC data is corrupt, attempt to read out of bounds.", + 1107, + )?)); + } + }; - let abc_file = Rc::new(read.read()?); - let tunit = TranslationUnit::from_abc(abc_file.clone(), domain, context.gc_context); - - for i in (0..abc_file.scripts.len()).rev() { + let num_scripts = abc.scripts.len(); + let tunit = TranslationUnit::from_abc(abc, domain, context.gc_context); + for i in (0..num_scripts).rev() { let mut script = tunit.load_script(i as u32, context)?; if !do_abc.flags.contains(DoAbcFlag::LAZY_INITIALIZE) { script.globals(context)?; } } - Ok(()) } diff --git a/core/src/avm2/error.rs b/core/src/avm2/error.rs index f2214fdfa..e01352e79 100644 --- a/core/src/avm2/error.rs +++ b/core/src/avm2/error.rs @@ -75,6 +75,17 @@ pub fn reference_error<'gc>( error_constructor(activation, class, message, code) } +#[inline(never)] +#[cold] +pub fn verify_error<'gc>( + activation: &mut Activation<'_, 'gc, '_>, + message: &str, + code: u32, +) -> Result, Error<'gc>> { + let class = activation.avm2().classes().verifyerror; + error_constructor(activation, class, message, code) +} + fn error_constructor<'gc>( activation: &mut Activation<'_, 'gc, '_>, class: ClassObject<'gc>, @@ -122,12 +133,6 @@ impl<'gc> From for Error<'gc> { } } -impl<'gc> From for Error<'gc> { - fn from(val: swf::error::Error) -> Error<'gc> { - Error::RustError(val.into()) - } -} - impl<'gc> From for Error<'gc> { fn from(val: crate::tag_utils::Error) -> Error<'gc> { Error::RustError(val.into()) diff --git a/core/src/avm2/globals.rs b/core/src/avm2/globals.rs index 49a1ad1ec..39f9d5448 100644 --- a/core/src/avm2/globals.rs +++ b/core/src/avm2/globals.rs @@ -108,6 +108,7 @@ pub struct SystemClasses<'gc> { pub referenceerror: ClassObject<'gc>, pub argumenterror: ClassObject<'gc>, pub typeerror: ClassObject<'gc>, + pub verifyerror: ClassObject<'gc>, } impl<'gc> SystemClasses<'gc> { @@ -183,6 +184,7 @@ impl<'gc> SystemClasses<'gc> { referenceerror: object, argumenterror: object, typeerror: object, + verifyerror: object, } } } @@ -697,6 +699,7 @@ fn load_playerglobal<'gc>( ("", "RangeError", rangeerror), ("", "ReferenceError", referenceerror), ("", "TypeError", typeerror), + ("", "VerifyError", verifyerror), ("", "XML", xml), ("", "XMLList", xml_list), ("flash.display", "Scene", scene), diff --git a/core/src/avm2/script.rs b/core/src/avm2/script.rs index d3d450975..aa977a28e 100644 --- a/core/src/avm2/script.rs +++ b/core/src/avm2/script.rs @@ -87,7 +87,7 @@ pub struct TranslationUnitData<'gc> { impl<'gc> TranslationUnit<'gc> { /// Construct a new `TranslationUnit` for a given ABC file intended to /// execute within a particular domain. - pub fn from_abc(abc: Rc, domain: Domain<'gc>, mc: MutationContext<'gc, '_>) -> Self { + pub fn from_abc(abc: AbcFile, domain: Domain<'gc>, mc: MutationContext<'gc, '_>) -> Self { let classes = vec![None; abc.classes.len()]; let methods = vec![None; abc.methods.len()]; let scripts = vec![None; abc.scripts.len()]; @@ -99,7 +99,7 @@ impl<'gc> TranslationUnit<'gc> { mc, TranslationUnitData { domain, - abc, + abc: Rc::new(abc), classes, methods, scripts,