From 0ea564f75cd522733aa7d4a6be4542c867a040a0 Mon Sep 17 00:00:00 2001 From: CUB3D Date: Tue, 30 Mar 2021 01:42:36 +0100 Subject: [PATCH] avm2: Implement Op::EscXAttr and Op::EscXElem --- core/src/avm2/activation.rs | 50 +++++++++++++++++++- core/tests/regression_tests.rs | 1 + core/tests/swfs/avm2/op_escxattr/Test.as | 9 ++++ core/tests/swfs/avm2/op_escxattr/output.txt | 2 + core/tests/swfs/avm2/op_escxattr/test.fla | Bin 0 -> 4796 bytes core/tests/swfs/avm2/op_escxattr/test.swf | Bin 0 -> 674 bytes 6 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 core/tests/swfs/avm2/op_escxattr/Test.as create mode 100644 core/tests/swfs/avm2/op_escxattr/output.txt create mode 100644 core/tests/swfs/avm2/op_escxattr/test.fla create mode 100644 core/tests/swfs/avm2/op_escxattr/test.swf diff --git a/core/src/avm2/activation.rs b/core/src/avm2/activation.rs index 41c8cd97d..cf925a056 100644 --- a/core/src/avm2/activation.rs +++ b/core/src/avm2/activation.rs @@ -678,6 +678,8 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> { Op::DebugFile { file_name } => self.op_debug_file(method, file_name), Op::DebugLine { line_num } => self.op_debug_line(line_num), Op::TypeOf => self.op_type_of(), + Op::EscXAttr => self.op_esc_xattr(), + Op::EscXElem => self.op_esc_elem(), _ => self.unknown_op(op), }; @@ -2321,7 +2323,53 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> { Ok(FrameControl::Continue) } - #[allow(unused_variables)] + /// Implements `Op::EscXAttr` + fn op_esc_xattr(&mut self) -> Result, Error> { + //TODO: does this coerce or type error if not string + let s = self.context.avm2.pop().coerce_to_string(self)?; + + // Implementation of `EscapeAttributeValue` from ECMA-357(10.2.1.2) + let mut r = String::new(); + for c in s.chars() { + match c { + '"' => r += """, + '<' => r += "<", + '&' => r += "&", + '\u{000A}' => r += " ", + '\u{000D}' => r += " ", + '\u{0009}' => r += " ", + _ => r.push(c) + } + } + self.context.avm2.push(AvmString::new(self.context.gc_context, r)); + + Ok(FrameControl::Continue) + } + + /// Implements `Op::EscXElem` + fn op_esc_elem(&mut self) -> Result, Error> { + //TODO: does this coerce or type error if not string + let s = self.context.avm2.pop().coerce_to_string(self)?; + + //TODO: does this use escapeelement or escape value as the spec says, guessing the spec is wrong, but needs testing to be sure + + // contrary to the avmplus documentation, this escapes the value on the top of the stack using EscapeElementValue from ECMA-357 *NOT* EscapeAttributeValue. + // Implementation of `EscapeElementValue` from ECMA-357(10.2.1.1) + let mut r = String::new(); + for c in s.chars() { + match c { + '<' => r += "<", + '>' => r += ">", + '&' => r += "&", + _ => r.push(c) + } + } + self.context.avm2.push(AvmString::new(self.context.gc_context, r)); + + Ok(FrameControl::Continue) + } + + #[allow(unused_variables)] #[cfg(avm_debug)] fn op_debug( &mut self, diff --git a/core/tests/regression_tests.rs b/core/tests/regression_tests.rs index d56d84fa7..125ebce89 100644 --- a/core/tests/regression_tests.rs +++ b/core/tests/regression_tests.rs @@ -541,6 +541,7 @@ swf_tests! { (as3_shape_drawrect, "avm2/shape_drawrect", 1), (as3_movieclip_drawrect, "avm2/movieclip_drawrect", 1), (as3_get_timer, "avm2/get_timer", 1), + (as3_op_escxattr, "avm2/op_escxattr", 1), } // TODO: These tests have some inaccuracies currently, so we use approx_eq to test that numeric values are close enough. diff --git a/core/tests/swfs/avm2/op_escxattr/Test.as b/core/tests/swfs/avm2/op_escxattr/Test.as new file mode 100644 index 000000000..906ae4677 --- /dev/null +++ b/core/tests/swfs/avm2/op_escxattr/Test.as @@ -0,0 +1,9 @@ +package { + public class Test { + } +} + +// Makes finding this is jpexs possible +var x = new XML(); +trace("// EscXAttr( \'TestString<&>#\\n\\r\\tTest!\"£$%^&*()\' )"); +trace("TestString<&>#\\n\\r\\tTest!\"£$%^&*()"); diff --git a/core/tests/swfs/avm2/op_escxattr/output.txt b/core/tests/swfs/avm2/op_escxattr/output.txt new file mode 100644 index 000000000..0673b8359 --- /dev/null +++ b/core/tests/swfs/avm2/op_escxattr/output.txt @@ -0,0 +1,2 @@ +// EscXAttr( 'TestString<&>#\n\r\tTest!"£$%^&*()' ) +TestString<&>#\n\r\tTest!"£$%^&*() diff --git a/core/tests/swfs/avm2/op_escxattr/test.fla b/core/tests/swfs/avm2/op_escxattr/test.fla new file mode 100644 index 0000000000000000000000000000000000000000..d9a9f85049c2afdd19cd0384f0fb0228b7ba80c7 GIT binary patch literal 4796 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 literal 0 HcmV?d00001 diff --git a/core/tests/swfs/avm2/op_escxattr/test.swf b/core/tests/swfs/avm2/op_escxattr/test.swf new file mode 100644 index 0000000000000000000000000000000000000000..b4ad3f2152538cfbd1fd01c6c87b869055bd540b GIT binary patch literal 674 zcmV;T0$u$>S5prz1ONbdoSjnbP7^^CotgcZ?)DRbQqXFZ@+GES6v2QIwV;Axqb1lM zTiazjwM)vj*&QnW^+`;817Co|C#XMskMaa~#|2XpjKGE@by#X50DYr8fn4bJ^G`c+d0u8+Y%#x|c)8qha7;RI-`N zG7AVDk9?5?08awtM7WBy9p>}ASf)5E)ke!&*|r>a$2njv$7T6nXv4D(*uwl@Sc9l6 zWYyx{KC^k~oDmshL;>)dxw_+bTGj_`yWMqIq2+W&FVs_mU(khY&hoR120mId&E3bv za%uOq=^Zv2EoRznkD21UZ~E^WzG-z2Zkz2+mHGCO#kp7Av+Dlp>Y0dC-hQEQ&$8KK zKA+j}?eZhw%w}dpy~I7oeRqHQ!KCS$p2-Dv{l?eN*{QeFH)rQ&GINvvKue!rCO3GQ zl`}(QR=xg2WF^~kI(+gErqq6s%xTkPsmRL!yd- zRw~y!&p}Ip3&PxC-J@xh~P_0Jp;C+LTkjRkupj*G3;q2RMECHWU2j7 zMZa~asN=o{$*}iC#~;6cdj|b5*7QIcI_cp!2#tUc-oj|EF9EDb04INTtb|XJeVj$T zhEfcZK7p!AKw!RSFeExhj9S#F#f)0qs3nY=3~w2ygQqE-r28p2vNk+%X2ylXfgVET I2icb)6j~oq$N&HU literal 0 HcmV?d00001