avm2: Throw `VerifyError` for invalid ABC files
This commit is contained in:
parent
a894ec5ca8
commit
95de87ad0a
|
@ -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(())
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Value<'gc>, 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<std::fmt::Error> for Error<'gc> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'gc> From<swf::error::Error> for Error<'gc> {
|
||||
fn from(val: swf::error::Error) -> Error<'gc> {
|
||||
Error::RustError(val.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> From<crate::tag_utils::Error> for Error<'gc> {
|
||||
fn from(val: crate::tag_utils::Error) -> Error<'gc> {
|
||||
Error::RustError(val.into())
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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<AbcFile>, 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,
|
||||
|
|
Loading…
Reference in New Issue