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.
/// This will completely prevent any further actions from being executed.
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> {
@ -126,6 +130,7 @@ impl<'gc> Avm1<'gc> {
Value::Undefined,
],
halted: false,
max_recursion_depth: 255,
}
}
@ -377,6 +382,14 @@ impl<'gc> Avm1<'gc> {
pub fn prototypes(&self) -> &globals::SystemPrototypes<'gc> {
&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>(

View File

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

View File

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

View File

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

View File

@ -325,6 +325,9 @@ impl<'gc> MovieClip<'gc> {
reader,
&mut cur_frame,
),
TagCode::ScriptLimits => {
self.0.write(context.gc_context).script_limits(reader, avm)
}
TagCode::SoundStreamHead => self
.0
.write(context.gc_context)
@ -2065,6 +2068,20 @@ impl<'gc, 'a> MovieClipData<'gc> {
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]
fn export_assets(
&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