swf: Make avm2 Reader operate directly with byte slices
This commit is contained in:
parent
73b251d6ec
commit
dad21d4398
|
@ -1460,7 +1460,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||
let val = self.context.avm1.pop();
|
||||
if val.as_bool(self.current_swf_version()) {
|
||||
self.seek(jump_offset, reader, data)?;
|
||||
reader.seek(data.as_ref(), jump_offset);
|
||||
}
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
@ -1543,7 +1543,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
reader: &mut Reader<'b>,
|
||||
data: &'b SwfSlice,
|
||||
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||
self.seek(jump_offset, reader, data)?;
|
||||
reader.seek(data.as_ref(), jump_offset);
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
||||
|
@ -3008,18 +3008,4 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
Ok(FrameControl::Continue)
|
||||
}
|
||||
}
|
||||
|
||||
fn seek<'b>(
|
||||
&self,
|
||||
jump_offset: i16,
|
||||
reader: &mut Reader<'b>,
|
||||
data: &'b SwfSlice,
|
||||
) -> Result<(), Error<'gc>> {
|
||||
let slice = data.movie.data();
|
||||
let mut pos = reader.get_ref().as_ptr() as usize - slice.as_ptr() as usize;
|
||||
pos = (pos as isize + isize::from(jump_offset)) as usize;
|
||||
pos = pos.min(slice.len());
|
||||
*reader.get_mut() = &slice[pos as usize..];
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ use crate::avm2::{value, Avm2, Error};
|
|||
use crate::context::UpdateContext;
|
||||
use gc_arena::{Gc, GcCell, MutationContext};
|
||||
use smallvec::SmallVec;
|
||||
use std::io::Cursor;
|
||||
use swf::avm2::read::Reader;
|
||||
use swf::avm2::types::{
|
||||
Class as AbcClass, Index, Method as AbcMethod, Multiname as AbcMultiname,
|
||||
|
@ -507,10 +506,11 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
let body: Result<_, Error> = method
|
||||
.body()
|
||||
.ok_or_else(|| "Cannot execute non-native method without body".into());
|
||||
let mut read = Reader::new(Cursor::new(body?.code.as_ref()));
|
||||
let body = body?;
|
||||
let mut reader = Reader::new(&body.code);
|
||||
|
||||
loop {
|
||||
let result = self.do_next_opcode(method, &mut read);
|
||||
let result = self.do_next_opcode(method, &mut reader, &body.code);
|
||||
match result {
|
||||
Ok(FrameControl::Return(value)) => break Ok(value),
|
||||
Ok(FrameControl::Continue) => {}
|
||||
|
@ -520,10 +520,11 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
}
|
||||
|
||||
/// Run a single action from a given action reader.
|
||||
fn do_next_opcode(
|
||||
fn do_next_opcode<'b>(
|
||||
&mut self,
|
||||
method: Gc<'gc, BytecodeMethod<'gc>>,
|
||||
reader: &mut Reader<Cursor<&[u8]>>,
|
||||
reader: &mut Reader<'b>,
|
||||
full_data: &'b [u8],
|
||||
) -> Result<FrameControl<'gc>, Error> {
|
||||
if self.context.update_start.elapsed() >= self.context.max_execution_duration {
|
||||
return Err(
|
||||
|
@ -635,21 +636,21 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
Op::SubtractI => self.op_subtract_i(),
|
||||
Op::Swap => self.op_swap(),
|
||||
Op::URShift => self.op_urshift(),
|
||||
Op::Jump { offset } => self.op_jump(offset, reader),
|
||||
Op::IfTrue { offset } => self.op_if_true(offset, reader),
|
||||
Op::IfFalse { offset } => self.op_if_false(offset, reader),
|
||||
Op::IfStrictEq { offset } => self.op_if_strict_eq(offset, reader),
|
||||
Op::IfStrictNe { offset } => self.op_if_strict_ne(offset, reader),
|
||||
Op::IfEq { offset } => self.op_if_eq(offset, reader),
|
||||
Op::IfNe { offset } => self.op_if_ne(offset, reader),
|
||||
Op::IfGe { offset } => self.op_if_ge(offset, reader),
|
||||
Op::IfGt { offset } => self.op_if_gt(offset, reader),
|
||||
Op::IfLe { offset } => self.op_if_le(offset, reader),
|
||||
Op::IfLt { offset } => self.op_if_lt(offset, reader),
|
||||
Op::IfNge { offset } => self.op_if_nge(offset, reader),
|
||||
Op::IfNgt { offset } => self.op_if_ngt(offset, reader),
|
||||
Op::IfNle { offset } => self.op_if_nle(offset, reader),
|
||||
Op::IfNlt { offset } => self.op_if_nlt(offset, reader),
|
||||
Op::Jump { offset } => self.op_jump(offset, reader, full_data),
|
||||
Op::IfTrue { offset } => self.op_if_true(offset, reader, full_data),
|
||||
Op::IfFalse { offset } => self.op_if_false(offset, reader, full_data),
|
||||
Op::IfStrictEq { offset } => self.op_if_strict_eq(offset, reader, full_data),
|
||||
Op::IfStrictNe { offset } => self.op_if_strict_ne(offset, reader, full_data),
|
||||
Op::IfEq { offset } => self.op_if_eq(offset, reader, full_data),
|
||||
Op::IfNe { offset } => self.op_if_ne(offset, reader, full_data),
|
||||
Op::IfGe { offset } => self.op_if_ge(offset, reader, full_data),
|
||||
Op::IfGt { offset } => self.op_if_gt(offset, reader, full_data),
|
||||
Op::IfLe { offset } => self.op_if_le(offset, reader, full_data),
|
||||
Op::IfLt { offset } => self.op_if_lt(offset, reader, full_data),
|
||||
Op::IfNge { offset } => self.op_if_nge(offset, reader, full_data),
|
||||
Op::IfNgt { offset } => self.op_if_ngt(offset, reader, full_data),
|
||||
Op::IfNle { offset } => self.op_if_nle(offset, reader, full_data),
|
||||
Op::IfNlt { offset } => self.op_if_nlt(offset, reader, full_data),
|
||||
Op::StrictEquals => self.op_strict_equals(),
|
||||
Op::Equals => self.op_equals(),
|
||||
Op::GreaterEquals => self.op_greater_equals(),
|
||||
|
@ -1834,219 +1835,234 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
||||
fn op_jump(
|
||||
fn op_jump<'b>(
|
||||
&mut self,
|
||||
offset: i32,
|
||||
reader: &mut Reader<Cursor<&[u8]>>,
|
||||
reader: &mut Reader<'b>,
|
||||
full_data: &'b [u8],
|
||||
) -> Result<FrameControl<'gc>, Error> {
|
||||
reader.seek(offset as i64)?;
|
||||
reader.seek(full_data, offset);
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
||||
fn op_if_true(
|
||||
fn op_if_true<'b>(
|
||||
&mut self,
|
||||
offset: i32,
|
||||
reader: &mut Reader<Cursor<&[u8]>>,
|
||||
reader: &mut Reader<'b>,
|
||||
full_data: &'b [u8],
|
||||
) -> Result<FrameControl<'gc>, Error> {
|
||||
let value = self.context.avm2.pop().coerce_to_boolean();
|
||||
|
||||
if value {
|
||||
reader.seek(offset as i64)?;
|
||||
reader.seek(full_data, offset);
|
||||
}
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
||||
fn op_if_false(
|
||||
fn op_if_false<'b>(
|
||||
&mut self,
|
||||
offset: i32,
|
||||
reader: &mut Reader<Cursor<&[u8]>>,
|
||||
reader: &mut Reader<'b>,
|
||||
full_data: &'b [u8],
|
||||
) -> Result<FrameControl<'gc>, Error> {
|
||||
let value = self.context.avm2.pop().coerce_to_boolean();
|
||||
|
||||
if !value {
|
||||
reader.seek(offset as i64)?;
|
||||
reader.seek(full_data, offset);
|
||||
}
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
||||
fn op_if_strict_eq(
|
||||
fn op_if_strict_eq<'b>(
|
||||
&mut self,
|
||||
offset: i32,
|
||||
reader: &mut Reader<Cursor<&[u8]>>,
|
||||
reader: &mut Reader<'b>,
|
||||
full_data: &'b [u8],
|
||||
) -> Result<FrameControl<'gc>, Error> {
|
||||
let value2 = self.context.avm2.pop();
|
||||
let value1 = self.context.avm2.pop();
|
||||
|
||||
if value1 == value2 {
|
||||
reader.seek(offset as i64)?;
|
||||
reader.seek(full_data, offset);
|
||||
}
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
||||
fn op_if_strict_ne(
|
||||
fn op_if_strict_ne<'b>(
|
||||
&mut self,
|
||||
offset: i32,
|
||||
reader: &mut Reader<Cursor<&[u8]>>,
|
||||
reader: &mut Reader<'b>,
|
||||
full_data: &'b [u8],
|
||||
) -> Result<FrameControl<'gc>, Error> {
|
||||
let value2 = self.context.avm2.pop();
|
||||
let value1 = self.context.avm2.pop();
|
||||
|
||||
if value1 != value2 {
|
||||
reader.seek(offset as i64)?;
|
||||
reader.seek(full_data, offset);
|
||||
}
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
||||
fn op_if_eq(
|
||||
fn op_if_eq<'b>(
|
||||
&mut self,
|
||||
offset: i32,
|
||||
reader: &mut Reader<Cursor<&[u8]>>,
|
||||
reader: &mut Reader<'b>,
|
||||
full_data: &'b [u8],
|
||||
) -> Result<FrameControl<'gc>, Error> {
|
||||
let value2 = self.context.avm2.pop();
|
||||
let value1 = self.context.avm2.pop();
|
||||
|
||||
if value1.abstract_eq(&value2, self)? {
|
||||
reader.seek(offset as i64)?;
|
||||
reader.seek(full_data, offset);
|
||||
}
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
||||
fn op_if_ne(
|
||||
fn op_if_ne<'b>(
|
||||
&mut self,
|
||||
offset: i32,
|
||||
reader: &mut Reader<Cursor<&[u8]>>,
|
||||
reader: &mut Reader<'b>,
|
||||
full_data: &'b [u8],
|
||||
) -> Result<FrameControl<'gc>, Error> {
|
||||
let value2 = self.context.avm2.pop();
|
||||
let value1 = self.context.avm2.pop();
|
||||
|
||||
if !value1.abstract_eq(&value2, self)? {
|
||||
reader.seek(offset as i64)?;
|
||||
reader.seek(full_data, offset);
|
||||
}
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
||||
fn op_if_ge(
|
||||
fn op_if_ge<'b>(
|
||||
&mut self,
|
||||
offset: i32,
|
||||
reader: &mut Reader<Cursor<&[u8]>>,
|
||||
reader: &mut Reader<'b>,
|
||||
full_data: &'b [u8],
|
||||
) -> Result<FrameControl<'gc>, Error> {
|
||||
let value2 = self.context.avm2.pop();
|
||||
let value1 = self.context.avm2.pop();
|
||||
|
||||
if value1.abstract_lt(&value2, self)? == Some(false) {
|
||||
reader.seek(offset as i64)?;
|
||||
reader.seek(full_data, offset);
|
||||
}
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
||||
fn op_if_gt(
|
||||
fn op_if_gt<'b>(
|
||||
&mut self,
|
||||
offset: i32,
|
||||
reader: &mut Reader<Cursor<&[u8]>>,
|
||||
reader: &mut Reader<'b>,
|
||||
full_data: &'b [u8],
|
||||
) -> Result<FrameControl<'gc>, Error> {
|
||||
let value2 = self.context.avm2.pop();
|
||||
let value1 = self.context.avm2.pop();
|
||||
|
||||
if value2.abstract_lt(&value1, self)? == Some(true) {
|
||||
reader.seek(offset as i64)?;
|
||||
reader.seek(full_data, offset);
|
||||
}
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
||||
fn op_if_le(
|
||||
fn op_if_le<'b>(
|
||||
&mut self,
|
||||
offset: i32,
|
||||
reader: &mut Reader<Cursor<&[u8]>>,
|
||||
reader: &mut Reader<'b>,
|
||||
full_data: &'b [u8],
|
||||
) -> Result<FrameControl<'gc>, Error> {
|
||||
let value2 = self.context.avm2.pop();
|
||||
let value1 = self.context.avm2.pop();
|
||||
|
||||
if value2.abstract_lt(&value1, self)? == Some(false) {
|
||||
reader.seek(offset as i64)?;
|
||||
reader.seek(full_data, offset);
|
||||
}
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
||||
fn op_if_lt(
|
||||
fn op_if_lt<'b>(
|
||||
&mut self,
|
||||
offset: i32,
|
||||
reader: &mut Reader<Cursor<&[u8]>>,
|
||||
reader: &mut Reader<'b>,
|
||||
full_data: &'b [u8],
|
||||
) -> Result<FrameControl<'gc>, Error> {
|
||||
let value2 = self.context.avm2.pop();
|
||||
let value1 = self.context.avm2.pop();
|
||||
|
||||
if value1.abstract_lt(&value2, self)? == Some(true) {
|
||||
reader.seek(offset as i64)?;
|
||||
reader.seek(full_data, offset);
|
||||
}
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
||||
fn op_if_nge(
|
||||
fn op_if_nge<'b>(
|
||||
&mut self,
|
||||
offset: i32,
|
||||
reader: &mut Reader<Cursor<&[u8]>>,
|
||||
reader: &mut Reader<'b>,
|
||||
full_data: &'b [u8],
|
||||
) -> Result<FrameControl<'gc>, Error> {
|
||||
let value2 = self.context.avm2.pop();
|
||||
let value1 = self.context.avm2.pop();
|
||||
|
||||
if value1.abstract_lt(&value2, self)?.unwrap_or(true) {
|
||||
reader.seek(offset as i64)?;
|
||||
reader.seek(full_data, offset);
|
||||
}
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
||||
fn op_if_ngt(
|
||||
fn op_if_ngt<'b>(
|
||||
&mut self,
|
||||
offset: i32,
|
||||
reader: &mut Reader<Cursor<&[u8]>>,
|
||||
reader: &mut Reader<'b>,
|
||||
full_data: &'b [u8],
|
||||
) -> Result<FrameControl<'gc>, Error> {
|
||||
let value2 = self.context.avm2.pop();
|
||||
let value1 = self.context.avm2.pop();
|
||||
|
||||
if !value2.abstract_lt(&value1, self)?.unwrap_or(false) {
|
||||
reader.seek(offset as i64)?;
|
||||
reader.seek(full_data, offset);
|
||||
}
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
||||
fn op_if_nle(
|
||||
fn op_if_nle<'b>(
|
||||
&mut self,
|
||||
offset: i32,
|
||||
reader: &mut Reader<Cursor<&[u8]>>,
|
||||
reader: &mut Reader<'b>,
|
||||
full_data: &'b [u8],
|
||||
) -> Result<FrameControl<'gc>, Error> {
|
||||
let value2 = self.context.avm2.pop();
|
||||
let value1 = self.context.avm2.pop();
|
||||
|
||||
if value2.abstract_lt(&value1, self)?.unwrap_or(true) {
|
||||
reader.seek(offset as i64)?;
|
||||
reader.seek(full_data, offset);
|
||||
}
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
||||
fn op_if_nlt(
|
||||
fn op_if_nlt<'b>(
|
||||
&mut self,
|
||||
offset: i32,
|
||||
reader: &mut Reader<Cursor<&[u8]>>,
|
||||
reader: &mut Reader<'b>,
|
||||
full_data: &'b [u8],
|
||||
) -> Result<FrameControl<'gc>, Error> {
|
||||
let value2 = self.context.avm2.pop();
|
||||
let value1 = self.context.avm2.pop();
|
||||
|
||||
if !value1.abstract_lt(&value2, self)?.unwrap_or(false) {
|
||||
reader.seek(offset as i64)?;
|
||||
reader.seek(full_data, offset);
|
||||
}
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
|
|
|
@ -29,6 +29,13 @@ impl<'a> Reader<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn seek(&mut self, data: &'a [u8], jump_offset: i16) {
|
||||
let mut pos = self.input.as_ptr() as usize - data.as_ptr() as usize;
|
||||
pos = (pos as isize + isize::from(jump_offset)) as usize;
|
||||
pos = pos.min(data.len());
|
||||
self.input = &data[pos as usize..];
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn encoding(&self) -> &'static Encoding {
|
||||
SwfStr::encoding_for_version(self.version)
|
||||
|
|
|
@ -2,25 +2,23 @@ use crate::avm2::types::*;
|
|||
use crate::error::{Error, Result};
|
||||
use crate::read::SwfReadExt;
|
||||
use byteorder::{LittleEndian, ReadBytesExt};
|
||||
use std::io::{self, Read, Seek, SeekFrom};
|
||||
use std::io::{self, Read};
|
||||
|
||||
pub struct Reader<R: Read> {
|
||||
input: R,
|
||||
pub struct Reader<'a> {
|
||||
input: &'a [u8],
|
||||
}
|
||||
|
||||
impl<R> Reader<R>
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
#[inline]
|
||||
pub fn seek(&mut self, relative_offset: i64) -> std::io::Result<u64> {
|
||||
self.input.seek(SeekFrom::Current(relative_offset as i64))
|
||||
impl<'a> Reader<'a> {
|
||||
pub fn new(input: &'a [u8]) -> Self {
|
||||
Self { input }
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read> Reader<R> {
|
||||
pub fn new(input: R) -> Reader<R> {
|
||||
Reader { input }
|
||||
#[inline]
|
||||
pub fn seek(&mut self, data: &'a [u8], relative_offset: i32) {
|
||||
let mut pos = self.input.as_ptr() as usize - data.as_ptr() as usize;
|
||||
pos = (pos as isize + relative_offset as isize) as usize;
|
||||
pos = pos.min(data.len());
|
||||
self.input = &data[pos as usize..];
|
||||
}
|
||||
|
||||
pub fn read(&mut self) -> Result<AbcFile> {
|
||||
|
@ -861,7 +859,7 @@ impl<R: Read> Reader<R> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, R: 'a + Read> SwfReadExt for Reader<R> {
|
||||
impl<'a> SwfReadExt for Reader<'a> {
|
||||
#[inline]
|
||||
fn read_u8(&mut self) -> io::Result<u8> {
|
||||
self.input.read_u8()
|
||||
|
|
Loading…
Reference in New Issue