From 176b70b1cd465329d8762f07cf1d917421b13d39 Mon Sep 17 00:00:00 2001 From: Adrian Wielgosik Date: Mon, 9 Sep 2024 20:49:53 +0200 Subject: [PATCH] avm2: Cache method body index on Method --- core/src/avm2/method.rs | 19 ++++--------------- swf/src/avm2/read.rs | 11 +++++++++-- swf/src/avm2/types.rs | 2 ++ swf/src/test_data.rs | 2 ++ 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/core/src/avm2/method.rs b/core/src/avm2/method.rs index 0eaa3e7bb588..aa3e7ef0da94 100644 --- a/core/src/avm2/method.rs +++ b/core/src/avm2/method.rs @@ -166,6 +166,7 @@ impl<'gc> BytecodeMethod<'gc> { let abc = txunit.abc(); let mut signature = Vec::new(); let mut return_type = Multiname::any(); + let mut abc_method_body = None; if abc.methods.get(abc_method.0 as usize).is_some() { let method = &abc.methods[abc_method.0 as usize]; @@ -178,20 +179,8 @@ impl<'gc> BytecodeMethod<'gc> { .deref() .clone(); - for (index, method_body) in abc.method_bodies.iter().enumerate() { - if method_body.method.0 == abc_method.0 { - return Ok(Self { - txunit, - abc: txunit.abc(), - abc_method: abc_method.0, - abc_method_body: Some(index as u32), - verified_info: GcCell::new(activation.context.gc_context, None), - signature, - return_type, - is_function, - activation_class: Lock::new(None), - }); - } + if let Some(body) = method.body { + abc_method_body = Some(body.0); } } @@ -199,7 +188,7 @@ impl<'gc> BytecodeMethod<'gc> { txunit, abc: txunit.abc(), abc_method: abc_method.0, - abc_method_body: None, + abc_method_body, verified_info: GcCell::new(activation.context.gc_context, None), signature, return_type, diff --git a/swf/src/avm2/read.rs b/swf/src/avm2/read.rs index febc2c03f712..a4a258629c07 100644 --- a/swf/src/avm2/read.rs +++ b/swf/src/avm2/read.rs @@ -67,8 +67,14 @@ impl<'a> Reader<'a> { let len = self.read_u30()?; let mut method_bodies = Vec::with_capacity(len as usize); - for _ in 0..len { - method_bodies.push(self.read_method_body()?); + for body_idx in 0..len { + let body = self.read_method_body()?; + if methods[body.method.0 as usize].body.is_some() { + // TODO: this should somehow throw error 1121 in FP. + return Err(Error::invalid_data("Duplicate method body")); + } + methods[body.method.0 as usize].body = Some(Index::new(body_idx)); + method_bodies.push(body); } Ok(AbcFile { @@ -279,6 +285,7 @@ impl<'a> Reader<'a> { params, return_type, flags, + body: None, }) } diff --git a/swf/src/avm2/types.rs b/swf/src/avm2/types.rs index 4cf622ab5027..4fca9fdf266b 100644 --- a/swf/src/avm2/types.rs +++ b/swf/src/avm2/types.rs @@ -98,6 +98,8 @@ pub struct Method { pub params: Vec, pub return_type: Index, pub flags: MethodFlags, + // not an ABC MethodInfo property; bound when parsing MethodBodies + pub body: Option>, } bitflags! { diff --git a/swf/src/test_data.rs b/swf/src/test_data.rs index 65342e92a558..8fc6d4859a72 100644 --- a/swf/src/test_data.rs +++ b/swf/src/test_data.rs @@ -2688,12 +2688,14 @@ pub fn avm2_tests() -> Vec { params: vec![], return_type: Index::new(1), flags: MethodFlags::empty(), + body: Some(Index::new(0)), }, Method { name: Index::new(0), params: vec![], return_type: Index::new(0), flags: MethodFlags::empty(), + body: Some(Index::new(1)), }, ], metadata: vec![],