core: Limit tag parsing to slice of tag data

This commit is contained in:
Mike Welsh 2020-07-03 17:06:45 -07:00
parent c50c835790
commit 08569ae979
2 changed files with 290 additions and 231 deletions

View File

@ -146,7 +146,13 @@ impl<'gc> MovieClip<'gc> {
let mut reader = data.read_from(self.0.read().tag_stream_pos); let mut reader = data.read_from(self.0.read().tag_stream_pos);
let mut cur_frame = 1; let mut cur_frame = 1;
let mut ids = fnv::FnvHashMap::default(); let mut ids = fnv::FnvHashMap::default();
let tag_callback = |reader: &mut SwfStream<&[u8]>, tag_code, tag_len| match tag_code { let version = reader.version();
let tag_callback = |reader: &mut SwfStream<&[u8]>, tag_code, tag_len| {
let data = *reader.get_inner().get_ref();
let tag_pos = reader.get_inner().position() as usize;
let tag_slice = &data[tag_pos..tag_pos + tag_len];
let reader = &mut SwfStream::new(std::io::Cursor::new(tag_slice), version);
match tag_code {
TagCode::FileAttributes => { TagCode::FileAttributes => {
let attributes = reader.read_file_attributes()?; let attributes = reader.read_file_attributes()?;
if attributes.is_action_script_3 { if attributes.is_action_script_3 {
@ -314,27 +320,30 @@ impl<'gc> MovieClip<'gc> {
.0 .0
.write(context.gc_context) .write(context.gc_context)
.preload_remove_object(context, reader, &mut ids, 2), .preload_remove_object(context, reader, &mut ids, 2),
TagCode::ShowFrame => { TagCode::ShowFrame => self.0.write(context.gc_context).preload_show_frame(
self.0
.write(context.gc_context)
.preload_show_frame(context, reader, &mut cur_frame)
}
TagCode::SoundStreamHead => self.0.write(context.gc_context).preload_sound_stream_head(
context, context,
reader, reader,
cur_frame, &mut cur_frame,
&mut static_data,
1,
), ),
TagCode::SoundStreamHead => self
.0
.write(context.gc_context)
.preload_sound_stream_head(context, reader, cur_frame, &mut static_data, 1),
TagCode::SoundStreamHead2 => self TagCode::SoundStreamHead2 => self
.0 .0
.write(context.gc_context) .write(context.gc_context)
.preload_sound_stream_head(context, reader, cur_frame, &mut static_data, 2), .preload_sound_stream_head(context, reader, cur_frame, &mut static_data, 2),
TagCode::SoundStreamBlock => self TagCode::SoundStreamBlock => {
.0 self.0.write(context.gc_context).preload_sound_stream_block(
.write(context.gc_context) context,
.preload_sound_stream_block(context, reader, cur_frame, &mut static_data, tag_len), reader,
cur_frame,
&mut static_data,
tag_len,
)
}
_ => Ok(()), _ => Ok(()),
}
}; };
let _ = tag_utils::decode_tags(&mut reader, tag_callback, TagCode::End); let _ = tag_utils::decode_tags(&mut reader, tag_callback, TagCode::End);
self.0.write(context.gc_context).static_data = self.0.write(context.gc_context).static_data =
@ -643,8 +652,14 @@ impl<'gc> MovieClip<'gc> {
let mut has_stream_block = false; let mut has_stream_block = false;
drop(mc); drop(mc);
let version = reader.version();
use swf::TagCode; use swf::TagCode;
let tag_callback = |reader: &mut _, tag_code, tag_len| match tag_code { let tag_callback = |reader: &mut SwfStream<&[u8]>, tag_code, tag_len| {
let data = *reader.get_inner().get_ref();
let tag_pos = reader.get_inner().position() as usize;
let tag_slice = &data[tag_pos..tag_pos + tag_len];
let reader = &mut SwfStream::new(std::io::Cursor::new(tag_slice), version);
match tag_code {
TagCode::DoAction => self.do_action(self_display_object, context, reader, tag_len), TagCode::DoAction => self.do_action(self_display_object, context, reader, tag_len),
TagCode::PlaceObject if run_display_actions => { TagCode::PlaceObject if run_display_actions => {
self.place_object(self_display_object, avm, context, reader, tag_len, 1) self.place_object(self_display_object, avm, context, reader, tag_len, 1)
@ -658,8 +673,12 @@ impl<'gc> MovieClip<'gc> {
TagCode::PlaceObject4 if run_display_actions => { TagCode::PlaceObject4 if run_display_actions => {
self.place_object(self_display_object, avm, context, reader, tag_len, 4) self.place_object(self_display_object, avm, context, reader, tag_len, 4)
} }
TagCode::RemoveObject if run_display_actions => self.remove_object(context, reader, 1), TagCode::RemoveObject if run_display_actions => {
TagCode::RemoveObject2 if run_display_actions => self.remove_object(context, reader, 2), self.remove_object(context, reader, 1)
}
TagCode::RemoveObject2 if run_display_actions => {
self.remove_object(context, reader, 2)
}
TagCode::SetBackgroundColor => self.set_background_color(context, reader), TagCode::SetBackgroundColor => self.set_background_color(context, reader),
TagCode::StartSound => self.start_sound_1(context, reader), TagCode::StartSound => self.start_sound_1(context, reader),
TagCode::SoundStreamBlock => { TagCode::SoundStreamBlock => {
@ -667,6 +686,7 @@ impl<'gc> MovieClip<'gc> {
self.sound_stream_block(context, reader) self.sound_stream_block(context, reader)
} }
_ => Ok(()), _ => Ok(()),
}
}; };
let _ = tag_utils::decode_tags(&mut reader, tag_callback, TagCode::ShowFrame); let _ = tag_utils::decode_tags(&mut reader, tag_callback, TagCode::ShowFrame);
@ -807,23 +827,57 @@ impl<'gc> MovieClip<'gc> {
frame_pos = reader.get_inner().position(); frame_pos = reader.get_inner().position();
let mut mc = self.0.write(context.gc_context); let mut mc = self.0.write(context.gc_context);
let version = reader.version();
use swf::TagCode; use swf::TagCode;
let tag_callback = |reader: &mut _, tag_code, tag_len| match tag_code { let tag_callback = |reader: &mut SwfStream<&[u8]>, tag_code, tag_len| {
let data = *reader.get_inner().get_ref();
let tag_pos = reader.get_inner().position() as usize;
let tag_slice = &data[tag_pos..tag_pos + tag_len];
let reader = &mut SwfStream::new(std::io::Cursor::new(tag_slice), version);
match tag_code {
TagCode::PlaceObject => { TagCode::PlaceObject => {
index += 1; index += 1;
mc.goto_place_object(reader, tag_len, 1, &mut goto_commands, is_rewind, index) mc.goto_place_object(
reader,
tag_len,
1,
&mut goto_commands,
is_rewind,
index,
)
} }
TagCode::PlaceObject2 => { TagCode::PlaceObject2 => {
index += 1; index += 1;
mc.goto_place_object(reader, tag_len, 2, &mut goto_commands, is_rewind, index) mc.goto_place_object(
reader,
tag_len,
2,
&mut goto_commands,
is_rewind,
index,
)
} }
TagCode::PlaceObject3 => { TagCode::PlaceObject3 => {
index += 1; index += 1;
mc.goto_place_object(reader, tag_len, 3, &mut goto_commands, is_rewind, index) mc.goto_place_object(
reader,
tag_len,
3,
&mut goto_commands,
is_rewind,
index,
)
} }
TagCode::PlaceObject4 => { TagCode::PlaceObject4 => {
index += 1; index += 1;
mc.goto_place_object(reader, tag_len, 4, &mut goto_commands, is_rewind, index) mc.goto_place_object(
reader,
tag_len,
4,
&mut goto_commands,
is_rewind,
index,
)
} }
TagCode::RemoveObject => { TagCode::RemoveObject => {
mc.goto_remove_object(reader, 1, context, &mut goto_commands, is_rewind) mc.goto_remove_object(reader, 1, context, &mut goto_commands, is_rewind)
@ -832,6 +886,7 @@ impl<'gc> MovieClip<'gc> {
mc.goto_remove_object(reader, 2, context, &mut goto_commands, is_rewind) mc.goto_remove_object(reader, 2, context, &mut goto_commands, is_rewind)
} }
_ => Ok(()), _ => Ok(()),
}
}; };
let _ = tag_utils::decode_tags(&mut reader, tag_callback, TagCode::ShowFrame); let _ = tag_utils::decode_tags(&mut reader, tag_callback, TagCode::ShowFrame);
} }

View File

@ -342,6 +342,10 @@ impl<R: Read> Reader<R> {
} }
} }
pub fn version(&self) -> u8 {
self.version
}
/// Returns a reference to the underlying `Reader`. /// Returns a reference to the underlying `Reader`.
pub fn get_ref(&self) -> &R { pub fn get_ref(&self) -> &R {
&self.input &self.input