avm1: Respect ScriptLimits for recursion depth, and use that in infinite_recursion_function

This commit is contained in:
Nathan Adams 2020-07-08 22:03:00 +02:00 committed by Mike Welsh
parent 2b30fd32b7
commit ecbab536b5
8 changed files with 41 additions and 259 deletions

View File

@ -89,6 +89,10 @@ pub struct Avm1<'gc> {
/// If a serious error has occured, or a user has requested it, the AVM may be halted. /// If a serious error has occured, or a user has requested it, the AVM may be halted.
/// This will completely prevent any further actions from being executed. /// This will completely prevent any further actions from being executed.
halted: bool, halted: bool,
/// The maximum amount of functions that can be called before a `Error::FunctionRecursionLimit`
/// is raised. This defaults to 256 but can be changed per movie.
max_recursion_depth: u16,
} }
unsafe impl<'gc> gc_arena::Collect for Avm1<'gc> { unsafe impl<'gc> gc_arena::Collect for Avm1<'gc> {
@ -126,6 +130,7 @@ impl<'gc> Avm1<'gc> {
Value::Undefined, Value::Undefined,
], ],
halted: false, halted: false,
max_recursion_depth: 255,
} }
} }
@ -377,6 +382,14 @@ impl<'gc> Avm1<'gc> {
pub fn prototypes(&self) -> &globals::SystemPrototypes<'gc> { pub fn prototypes(&self) -> &globals::SystemPrototypes<'gc> {
&self.prototypes &self.prototypes
} }
pub fn max_recursion_depth(&self) -> u16 {
self.max_recursion_depth
}
pub fn set_max_recursion_depth(&mut self, max_recursion_depth: u16) {
self.max_recursion_depth = max_recursion_depth
}
} }
pub fn root_error_handler<'gc>( pub fn root_error_handler<'gc>(

View File

@ -94,7 +94,7 @@ pub struct ActivationIdentifier<'a> {
parent: Option<&'a ActivationIdentifier<'a>>, parent: Option<&'a ActivationIdentifier<'a>>,
name: Cow<'static, str>, name: Cow<'static, str>,
depth: u16, depth: u16,
function_count: u8, function_count: u16,
special_count: u8, special_count: u8,
} }
@ -127,7 +127,7 @@ impl<'a> ActivationIdentifier<'a> {
name: name.into(), name: name.into(),
depth: self.depth + 1, depth: self.depth + 1,
function_count: self.function_count, function_count: self.function_count,
special_count: self.function_count, special_count: self.special_count,
} }
} }
@ -135,11 +135,12 @@ impl<'a> ActivationIdentifier<'a> {
&'a self, &'a self,
name: S, name: S,
reason: ExecutionReason, reason: ExecutionReason,
max_recursion_depth: u16,
) -> Result<Self, Error<'gc>> { ) -> Result<Self, Error<'gc>> {
let (function_count, special_count) = match reason { let (function_count, special_count) = match reason {
ExecutionReason::FunctionCall => { ExecutionReason::FunctionCall => {
if self.function_count == 255 { if self.function_count >= max_recursion_depth - 1 {
return Err(Error::FunctionRecursionLimit); return Err(Error::FunctionRecursionLimit(max_recursion_depth));
} }
(self.function_count + 1, self.special_count) (self.function_count + 1, self.special_count)
} }

View File

@ -6,8 +6,8 @@ pub enum Error<'gc> {
#[error("Prototype recursion limit has been exceeded")] #[error("Prototype recursion limit has been exceeded")]
PrototypeRecursionLimit, PrototypeRecursionLimit,
#[error("256 levels of function recursion were exceeded in one action list. This is probably an infinite loop.")] #[error("{0} levels of function recursion were exceeded in one action list. This is probably an infinite loop.")]
FunctionRecursionLimit, FunctionRecursionLimit(u16),
#[error("66 levels of special recursion were exceeded in one action list. This is probably an infinite loop.")] #[error("66 levels of special recursion were exceeded in one action list. This is probably an infinite loop.")]
SpecialRecursionLimit, SpecialRecursionLimit,
@ -23,7 +23,7 @@ impl Error<'_> {
pub fn is_halting(&self) -> bool { pub fn is_halting(&self) -> bool {
match self { match self {
Error::PrototypeRecursionLimit => true, Error::PrototypeRecursionLimit => true,
Error::FunctionRecursionLimit => true, Error::FunctionRecursionLimit(_) => true,
Error::SpecialRecursionLimit => true, Error::SpecialRecursionLimit => true,
Error::InvalidSwf(_) => true, Error::InvalidSwf(_) => true,
Error::ThrownValue(_) => false, Error::ThrownValue(_) => false,

View File

@ -313,7 +313,9 @@ impl<'gc> Executable<'gc> {
let mut frame = Activation::from_action( let mut frame = Activation::from_action(
activation.avm, activation.avm,
activation.id.function(name, reason)?, activation
.id
.function(name, reason, activation.avm.max_recursion_depth())?,
effective_ver, effective_ver,
child_scope, child_scope,
af.constant_pool, af.constant_pool,

View File

@ -325,6 +325,9 @@ impl<'gc> MovieClip<'gc> {
reader, reader,
&mut cur_frame, &mut cur_frame,
), ),
TagCode::ScriptLimits => {
self.0.write(context.gc_context).script_limits(reader, avm)
}
TagCode::SoundStreamHead => self TagCode::SoundStreamHead => self
.0 .0
.write(context.gc_context) .write(context.gc_context)
@ -2065,6 +2068,20 @@ impl<'gc, 'a> MovieClipData<'gc> {
Ok(()) Ok(())
} }
#[inline]
fn script_limits(
&mut self,
reader: &mut SwfStream<&'a [u8]>,
avm: &mut Avm1<'gc>,
) -> DecodeResult {
let max_recursion_depth = reader.read_u16()?;
let _timeout_in_seconds = reader.read_u16()?;
avm.set_max_recursion_depth(max_recursion_depth);
Ok(())
}
#[inline] #[inline]
fn export_assets( fn export_assets(
&mut self, &mut self,

View File

@ -2,254 +2,3 @@
// start of recursive() function // start of recursive() function
// start of recursive() function // start of recursive() function
// start of recursive() function // start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function
// start of recursive() function