From c7966cea7754906b3b581b43b5544b9ac2958bb1 Mon Sep 17 00:00:00 2001 From: friedkeenan Date: Fri, 15 Dec 2023 12:16:50 -0600 Subject: [PATCH] swf: Add test for avm2 Writer::write_op --- swf/src/avm2/write.rs | 537 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 537 insertions(+) diff --git a/swf/src/avm2/write.rs b/swf/src/avm2/write.rs index 73e594eb0..fced28540 100644 --- a/swf/src/avm2/write.rs +++ b/swf/src/avm2/write.rs @@ -1082,4 +1082,541 @@ pub mod tests { assert_eq!(write(77777), &[0b1101_0001, 0b0010_1111, 0b0000_0001]); assert_eq!(write(-77777), &[0b0010_1111, 0b1101_0000, 0b1111_1110]); } + + #[test] + fn write_op() { + let write = |op| { + let mut out = vec![]; + + { + let mut writer = Writer::new(&mut out); + writer.write_op(&op).unwrap(); + } + + out + }; + + assert_eq!(write(Op::Add), b"\xA0"); + + assert_eq!(write(Op::AddI), b"\xC5"); + + assert_eq!(write(Op::ApplyType { num_types: 1 }), b"\x53\x01"); + + assert_eq!( + write(Op::AsType { + type_name: Index::new(1) + }), + b"\x86\x01" + ); + + assert_eq!(write(Op::AsTypeLate), b"\x87"); + + assert_eq!(write(Op::BitAnd), b"\xA8"); + + assert_eq!(write(Op::BitNot), b"\x97"); + + assert_eq!(write(Op::BitOr), b"\xA9"); + + assert_eq!(write(Op::BitXor), b"\xAA"); + + assert_eq!(write(Op::Bkpt), b"\x01"); + + assert_eq!(write(Op::BkptLine { line_num: 1 }), b"\xF2\x01"); + + assert_eq!(write(Op::Call { num_args: 1 }), b"\x41\x01"); + + assert_eq!( + write(Op::CallMethod { + index: Index::new(1), + num_args: 2 + }), + b"\x43\x01\x02" + ); + + assert_eq!( + write(Op::CallProperty { + index: Index::new(1), + num_args: 2 + }), + b"\x46\x01\x02" + ); + + assert_eq!( + write(Op::CallPropLex { + index: Index::new(1), + num_args: 2 + }), + b"\x4C\x01\x02" + ); + + assert_eq!( + write(Op::CallPropVoid { + index: Index::new(1), + num_args: 2 + }), + b"\x4F\x01\x02" + ); + + assert_eq!( + write(Op::CallStatic { + index: Index::new(1), + num_args: 2 + }), + b"\x44\x01\x02" + ); + + assert_eq!( + write(Op::CallSuper { + index: Index::new(1), + num_args: 2 + }), + b"\x45\x01\x02" + ); + + assert_eq!( + write(Op::CallSuperVoid { + index: Index::new(1), + num_args: 2 + }), + b"\x4E\x01\x02" + ); + + assert_eq!(write(Op::CheckFilter), b"\x78"); + + assert_eq!( + write(Op::Coerce { + index: Index::new(1) + }), + b"\x80\x01" + ); + + assert_eq!(write(Op::CoerceA), b"\x82"); + + assert_eq!(write(Op::CoerceB), b"\x81"); + + assert_eq!(write(Op::CoerceD), b"\x84"); + + assert_eq!(write(Op::CoerceI), b"\x83"); + + assert_eq!(write(Op::CoerceO), b"\x89"); + + assert_eq!(write(Op::CoerceS), b"\x85"); + + assert_eq!(write(Op::CoerceU), b"\x88"); + + assert_eq!(write(Op::Construct { num_args: 1 }), b"\x42\x01"); + + assert_eq!( + write(Op::ConstructProp { + index: Index::new(1), + num_args: 2 + }), + b"\x4A\x01\x02" + ); + + assert_eq!(write(Op::ConstructSuper { num_args: 1 }), b"\x49\x01"); + + assert_eq!(write(Op::ConvertB), b"\x76"); + + assert_eq!(write(Op::ConvertD), b"\x75"); + + assert_eq!(write(Op::ConvertI), b"\x73"); + + assert_eq!(write(Op::ConvertO), b"\x77"); + + assert_eq!(write(Op::ConvertS), b"\x70"); + + assert_eq!(write(Op::ConvertU), b"\x74"); + + assert_eq!( + write(Op::Debug { + is_local_register: true, + register_name: Index::new(2), + register: 3 + }), + b"\xEF\x01\x02\x03\x00" + ); + + assert_eq!( + write(Op::DebugFile { + file_name: Index::new(1) + }), + b"\xF1\x01" + ); + + assert_eq!(write(Op::DebugLine { line_num: 1 }), b"\xF0\x01"); + + assert_eq!(write(Op::DecLocal { index: 1 }), b"\x94\x01"); + + assert_eq!(write(Op::DecLocalI { index: 1 }), b"\xC3\x01"); + + assert_eq!(write(Op::Decrement), b"\x93"); + + assert_eq!(write(Op::DecrementI), b"\xC1"); + + assert_eq!( + write(Op::DeleteProperty { + index: Index::new(1) + }), + b"\x6A\x01" + ); + + assert_eq!(write(Op::Divide), b"\xA3"); + + assert_eq!(write(Op::Dup), b"\x2A"); + + assert_eq!( + write(Op::Dxns { + index: Index::new(1) + }), + b"\x06\x01" + ); + + assert_eq!(write(Op::DxnsLate), b"\x07"); + + assert_eq!(write(Op::Equals), b"\xAB"); + + assert_eq!(write(Op::EscXAttr), b"\x72"); + + assert_eq!(write(Op::EscXElem), b"\x71"); + + assert_eq!( + write(Op::FindDef { + index: Index::new(1) + }), + b"\x5F\x01" + ); + + assert_eq!( + write(Op::FindProperty { + index: Index::new(1) + }), + b"\x5E\x01" + ); + + assert_eq!( + write(Op::FindPropStrict { + index: Index::new(1) + }), + b"\x5D\x01" + ); + + assert_eq!( + write(Op::GetDescendants { + index: Index::new(1) + }), + b"\x59\x01" + ); + + assert_eq!(write(Op::GetGlobalScope), b"\x64"); + + assert_eq!(write(Op::GetGlobalSlot { index: 1 }), b"\x6E\x01"); + + assert_eq!( + write(Op::GetLex { + index: Index::new(1) + }), + b"\x60\x01" + ); + + assert_eq!(write(Op::GetLocal { index: 4 }), b"\x62\x04"); + + assert_eq!(write(Op::GetLocal { index: 0 }), b"\xD0"); + + assert_eq!(write(Op::GetLocal { index: 1 }), b"\xD1"); + + assert_eq!(write(Op::GetLocal { index: 2 }), b"\xD2"); + + assert_eq!(write(Op::GetLocal { index: 3 }), b"\xD3"); + + assert_eq!(write(Op::GetOuterScope { index: 1 }), b"\x67\x01"); + + assert_eq!( + write(Op::GetProperty { + index: Index::new(1) + }), + b"\x66\x01" + ); + + assert_eq!(write(Op::GetScopeObject { index: 1 }), b"\x65\x01"); + + assert_eq!(write(Op::GetSlot { index: 1 }), b"\x6C\x01"); + + assert_eq!( + write(Op::GetSuper { + index: Index::new(1) + }), + b"\x04\x01" + ); + + assert_eq!(write(Op::GreaterEquals), b"\xB0"); + + assert_eq!(write(Op::GreaterThan), b"\xAF"); + + assert_eq!(write(Op::HasNext), b"\x1F"); + + assert_eq!( + write(Op::HasNext2 { + object_register: 1, + index_register: 2 + }), + b"\x32\x01\x02" + ); + + assert_eq!(write(Op::IfEq { offset: 1 }), b"\x13\x01\x00\x00"); + + assert_eq!(write(Op::IfFalse { offset: 1 }), b"\x12\x01\x00\x00"); + + assert_eq!(write(Op::IfGe { offset: 1 }), b"\x18\x01\x00\x00"); + + assert_eq!(write(Op::IfGt { offset: 1 }), b"\x17\x01\x00\x00"); + + assert_eq!(write(Op::IfLe { offset: 1 }), b"\x16\x01\x00\x00"); + + assert_eq!(write(Op::IfLt { offset: 1 }), b"\x15\x01\x00\x00"); + + assert_eq!(write(Op::IfNe { offset: 1 }), b"\x14\x01\x00\x00"); + + assert_eq!(write(Op::IfNge { offset: 1 }), b"\x0F\x01\x00\x00"); + + assert_eq!(write(Op::IfNgt { offset: 1 }), b"\x0E\x01\x00\x00"); + + assert_eq!(write(Op::IfNle { offset: 1 }), b"\x0D\x01\x00\x00"); + + assert_eq!(write(Op::IfNlt { offset: 1 }), b"\x0C\x01\x00\x00"); + + assert_eq!(write(Op::IfStrictEq { offset: 1 }), b"\x19\x01\x00\x00"); + + assert_eq!(write(Op::IfStrictNe { offset: 1 }), b"\x1A\x01\x00\x00"); + + assert_eq!(write(Op::IfTrue { offset: 1 }), b"\x11\x01\x00\x00"); + + assert_eq!(write(Op::In), b"\xB4"); + + assert_eq!(write(Op::IncLocal { index: 1 }), b"\x92\x01"); + + assert_eq!(write(Op::IncLocalI { index: 1 }), b"\xC2\x01"); + + assert_eq!(write(Op::Increment), b"\x91"); + + assert_eq!(write(Op::IncrementI), b"\xC0"); + + assert_eq!( + write(Op::InitProperty { + index: Index::new(1) + }), + b"\x68\x01" + ); + + assert_eq!(write(Op::InstanceOf), b"\xB1"); + + assert_eq!( + write(Op::IsType { + index: Index::new(1) + }), + b"\xB2\x01" + ); + + assert_eq!(write(Op::IsTypeLate), b"\xB3"); + + assert_eq!(write(Op::Jump { offset: 1 }), b"\x10\x01\x00\x00"); + + assert_eq!(write(Op::Kill { index: 1 }), b"\x08\x01"); + + assert_eq!(write(Op::Label), b"\x09"); + + assert_eq!(write(Op::LessEquals), b"\xAE"); + + assert_eq!(write(Op::LessThan), b"\xAD"); + + assert_eq!(write(Op::Lf32), b"\x38"); + + assert_eq!(write(Op::Lf64), b"\x39"); + + assert_eq!(write(Op::Li16), b"\x36"); + + assert_eq!(write(Op::Li32), b"\x37"); + + assert_eq!(write(Op::Li8), b"\x35"); + + assert_eq!( + write(Op::LookupSwitch { + default_offset: 1, + case_offsets: Box::new([3, 4, 5]) + }), + b"\x1B\x01\x00\x00\x02\x03\x00\x00\x04\x00\x00\x05\x00\x00" + ); + + assert_eq!(write(Op::LShift), b"\xA5"); + + assert_eq!(write(Op::Modulo), b"\xA4"); + + assert_eq!(write(Op::Multiply), b"\xA2"); + + assert_eq!(write(Op::MultiplyI), b"\xC7"); + + assert_eq!(write(Op::Negate), b"\x90"); + + assert_eq!(write(Op::NegateI), b"\xC4"); + + assert_eq!(write(Op::NewActivation), b"\x57"); + + assert_eq!(write(Op::NewArray { num_args: 1 }), b"\x56\x01"); + + assert_eq!( + write(Op::NewCatch { + index: Index::new(1) + }), + b"\x5A\x01" + ); + + assert_eq!( + write(Op::NewClass { + index: Index::new(1) + }), + b"\x58\x01" + ); + + assert_eq!( + write(Op::NewFunction { + index: Index::new(1) + }), + b"\x40\x01" + ); + + assert_eq!(write(Op::NewObject { num_args: 1 }), b"\x55\x01"); + + assert_eq!(write(Op::NextName), b"\x1E"); + + assert_eq!(write(Op::NextValue), b"\x23"); + + assert_eq!(write(Op::Nop), b"\x02"); + + assert_eq!(write(Op::Not), b"\x96"); + + assert_eq!(write(Op::Pop), b"\x29"); + + assert_eq!(write(Op::PopScope), b"\x1D"); + + assert_eq!(write(Op::PushByte { value: 1 }), b"\x24\x01"); + + assert_eq!(write(Op::PushConstant { value: 1 }), b"\x22\x01"); + + assert_eq!( + write(Op::PushDouble { + value: Index::new(1) + }), + b"\x2F\x01" + ); + + assert_eq!(write(Op::PushFalse), b"\x27"); + + assert_eq!( + write(Op::PushInt { + value: Index::new(1) + }), + b"\x2D\x01" + ); + + assert_eq!( + write(Op::PushNamespace { + value: Index::new(1) + }), + b"\x31\x01" + ); + + assert_eq!(write(Op::PushNaN), b"\x28"); + + assert_eq!(write(Op::PushNull), b"\x20"); + + assert_eq!(write(Op::PushScope), b"\x30"); + + assert_eq!(write(Op::PushShort { value: 1 }), b"\x25\x01"); + + assert_eq!( + write(Op::PushString { + value: Index::new(1) + }), + b"\x2C\x01" + ); + + assert_eq!(write(Op::PushTrue), b"\x26"); + + assert_eq!( + write(Op::PushUint { + value: Index::new(1) + }), + b"\x2E\x01" + ); + + assert_eq!(write(Op::PushUndefined), b"\x21"); + + assert_eq!(write(Op::PushWith), b"\x1C"); + + assert_eq!(write(Op::ReturnValue), b"\x48"); + + assert_eq!(write(Op::ReturnVoid), b"\x47"); + + assert_eq!(write(Op::RShift), b"\xA6"); + + assert_eq!(write(Op::SetGlobalSlot { index: 1 }), b"\x6F\x01"); + + assert_eq!(write(Op::SetLocal { index: 4 }), b"\x63\x04"); + + assert_eq!(write(Op::SetLocal { index: 0 }), b"\xD4"); + + assert_eq!(write(Op::SetLocal { index: 1 }), b"\xD5"); + + assert_eq!(write(Op::SetLocal { index: 2 }), b"\xD6"); + + assert_eq!(write(Op::SetLocal { index: 3 }), b"\xD7"); + + assert_eq!( + write(Op::SetProperty { + index: Index::new(1) + }), + b"\x61\x01" + ); + + assert_eq!(write(Op::SetSlot { index: 1 }), b"\x6D\x01"); + + assert_eq!( + write(Op::SetSuper { + index: Index::new(1) + }), + b"\x05\x01" + ); + + assert_eq!(write(Op::Sf32), b"\x3D"); + + assert_eq!(write(Op::Sf64), b"\x3E"); + + assert_eq!(write(Op::Si16), b"\x3B"); + + assert_eq!(write(Op::Si32), b"\x3C"); + + assert_eq!(write(Op::Si8), b"\x3A"); + + assert_eq!(write(Op::StrictEquals), b"\xAC"); + + assert_eq!(write(Op::Subtract), b"\xA1"); + + assert_eq!(write(Op::SubtractI), b"\xC6"); + + assert_eq!(write(Op::Swap), b"\x2B"); + + assert_eq!(write(Op::Sxi1), b"\x50"); + + assert_eq!(write(Op::Sxi16), b"\x52"); + + assert_eq!(write(Op::Sxi8), b"\x51"); + + assert_eq!(write(Op::Throw), b"\x03"); + + assert_eq!(write(Op::Timestamp), b"\xF3"); + + assert_eq!(write(Op::TypeOf), b"\x95"); + + assert_eq!(write(Op::URShift), b"\xA7"); + } }