swf: Add `avm1::Action::End`

Returning an `Action::End` instead of `None` when reading the end
of an action.
This commit is contained in:
Mike Welsh 2022-01-16 17:19:45 -08:00
parent d5862809c7
commit 2b2346b65e
4 changed files with 19 additions and 15 deletions

View File

@ -458,7 +458,8 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
if reader.get_ref().as_ptr() as usize >= data.as_ref().as_ptr_range().end as usize {
//Executing beyond the end of a function constitutes an implicit return.
Ok(FrameControl::Return(ReturnType::Implicit))
} else if let Some(action) = reader.read_action()? {
} else {
let action = reader.read_action()?;
avm_debug!(
self.context.avm1,
"({}) Action: {:?}",
@ -492,6 +493,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
Action::Delete => self.action_delete(),
Action::Delete2 => self.action_delete_2(),
Action::Divide => self.action_divide(),
Action::End => self.action_end(),
Action::EndDrag => self.action_end_drag(),
Action::Enumerate => self.action_enumerate(),
Action::Enumerate2 => self.action_enumerate_2(),
@ -568,9 +570,6 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
Action::With(action) => self.action_with(action, data),
_ => self.unknown_op(action),
}
} else {
//The explicit end opcode was encountered so return here
Ok(FrameControl::Return(ReturnType::Implicit))
}
}
@ -1015,6 +1014,10 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
Ok(FrameControl::Continue)
}
fn action_end(&mut self) -> Result<FrameControl<'gc>, Error<'gc>> {
Ok(FrameControl::Return(ReturnType::Implicit))
}
fn action_end_drag(&mut self) -> Result<FrameControl<'gc>, Error<'gc>> {
*self.context.drag_object = None;
Ok(FrameControl::Continue)

View File

@ -49,7 +49,7 @@ impl<'a> Reader<'a> {
}
#[inline]
pub fn read_action(&mut self) -> Result<Option<Action<'a>>> {
pub fn read_action(&mut self) -> Result<Action<'a>> {
let (opcode, mut length) = self.read_opcode_and_length()?;
let start = self.input;
@ -87,11 +87,9 @@ impl<'a> Reader<'a> {
/// The `length` passed in should be the length excluding any sub-blocks.
/// The final `length` returned will be total length of the action, including sub-blocks.
#[inline]
fn read_op(&mut self, opcode: u8, length: &mut usize) -> Result<Option<Action<'a>>> {
fn read_op(&mut self, opcode: u8, length: &mut usize) -> Result<Action<'a>> {
let action = if let Some(op) = OpCode::from_u8(opcode) {
match op {
OpCode::End => return Ok(None),
OpCode::Add => Action::Add,
OpCode::Add2 => Action::Add2,
OpCode::And => Action::And,
@ -124,6 +122,7 @@ impl<'a> Reader<'a> {
OpCode::EndDrag => Action::EndDrag,
OpCode::Enumerate => Action::Enumerate,
OpCode::Enumerate2 => Action::Enumerate2,
OpCode::End => Action::End,
OpCode::Equals => Action::Equals,
OpCode::Equals2 => Action::Equals2,
OpCode::Extends => Action::Extends,
@ -200,7 +199,7 @@ impl<'a> Reader<'a> {
Action::Unknown(self.read_unknown_action(opcode, *length)?)
};
Ok(Some(action))
Ok(action)
}
fn read_constant_pool(&mut self) -> Result<ConstantPool<'a>> {
@ -420,7 +419,7 @@ pub mod tests {
fn read_action() {
for (swf_version, expected_action, action_bytes) in test_data::avm1_tests() {
let mut reader = Reader::new(&action_bytes[..], swf_version);
let parsed_action = reader.read_action().unwrap().unwrap();
let parsed_action = reader.read_action().unwrap();
assert_eq!(
parsed_action, expected_action,
"Incorrectly parsed action.\nRead:\n{:?}\n\nExpected:\n{:?}",
@ -450,7 +449,7 @@ pub mod tests {
0x00, 0x74, 0x65, 0x73, 0x74, 0x00, 0x26, 0x00,
];
let mut reader = Reader::new(&action_bytes[..], 5);
let action = reader.read_action().unwrap().unwrap();
let action = reader.read_action().unwrap();
assert_eq!(
action,
Action::DefineFunction(DefineFunction {
@ -462,7 +461,7 @@ pub mod tests {
if let Action::DefineFunction(DefineFunction { actions, .. }) = action {
let mut reader = Reader::new(actions, 5);
let action = reader.read_action().unwrap().unwrap();
let action = reader.read_action().unwrap();
assert_eq!(
action,
Action::Push(Push {
@ -480,7 +479,7 @@ pub mod tests {
// until the end of the action. Ensure we don't read extra values.
let action_bytes = [0x96, 2, 0, 2, 3, 3]; // Extra 3 at the end shouldn't be read.
let mut reader = Reader::new(&action_bytes[..], 5);
let action = reader.read_action().unwrap().unwrap();
let action = reader.read_action().unwrap();
assert_eq!(
action,
Action::Push(Push {
@ -504,7 +503,7 @@ pub mod tests {
];
let mut reader = Reader::new(&action_bytes[..], 5);
let action = reader.read_action().unwrap().unwrap();
let action = reader.read_action().unwrap();
assert_eq!(
action,
Action::ConstantPool(ConstantPool {
@ -512,7 +511,7 @@ pub mod tests {
})
);
let action = reader.read_action().unwrap().unwrap();
let action = reader.read_action().unwrap();
assert_eq!(action, Action::Subtract);
}
}

View File

@ -28,6 +28,7 @@ pub enum Action<'a> {
Delete,
Delete2,
Divide,
End,
EndDrag,
Enumerate,
Enumerate2,

View File

@ -103,6 +103,7 @@ impl<W: Write> Writer<W> {
Action::Divide => self.write_small_action(OpCode::Divide),
Action::Delete => self.write_small_action(OpCode::Delete),
Action::Delete2 => self.write_small_action(OpCode::Delete2),
Action::End => self.write_small_action(OpCode::End),
Action::EndDrag => self.write_small_action(OpCode::EndDrag),
Action::Enumerate => self.write_small_action(OpCode::Enumerate),
Action::Enumerate2 => self.write_small_action(OpCode::Enumerate2),