diff --git a/core/src/avm2/e4x.rs b/core/src/avm2/e4x.rs index 302fe96c0..893bddf88 100644 --- a/core/src/avm2/e4x.rs +++ b/core/src/avm2/e4x.rs @@ -11,7 +11,9 @@ use quick_xml::{ use crate::{avm2::TObject, xml::custom_unescape}; -use super::{object::E4XOrXml, string::AvmString, Activation, Error, Multiname, Value}; +use super::{ + error::type_error, object::E4XOrXml, string::AvmString, Activation, Error, Multiname, Value, +}; use crate::string::{WStr, WString}; /// The underlying XML node data, based on E4XNode in avmplus @@ -39,6 +41,17 @@ impl<'gc> Debug for E4XNodeData<'gc> { } } +fn malformed_element<'gc>(activation: &mut Activation<'_, 'gc>) -> Error<'gc> { + Error::AvmError( + type_error( + activation, + "Error #1090: XML parser failure: element is malformed.", + 1090, + ) + .expect("Failed to construct XML TypeError"), + ) +} + #[derive(Collect, Debug)] #[collect(no_drop)] pub enum E4XNodeKind<'gc> { @@ -365,13 +378,14 @@ impl<'gc> E4XNode<'gc> { } loop { - let event = parser.read_event().map_err(|error| { - Error::RustError(format!("XML parsing error: {error:?}").into()) - })?; + let event = parser + .read_event() + .map_err(|_| malformed_element(activation))?; match &event { Event::Start(bs) => { - let child = E4XNode::from_start_event(activation, bs, parser.decoder())?; + let child = E4XNode::from_start_event(activation, bs, parser.decoder()) + .map_err(|_| malformed_element(activation))?; if let Some(current_tag) = open_tags.last_mut() { current_tag.append_child(activation.context.gc_context, child)?; @@ -380,7 +394,8 @@ impl<'gc> E4XNode<'gc> { depth += 1; } Event::Empty(bs) => { - let node = E4XNode::from_start_event(activation, bs, parser.decoder())?; + let node = E4XNode::from_start_event(activation, bs, parser.decoder()) + .map_err(|_| malformed_element(activation))?; push_childless_node(node, &mut open_tags, &mut top_level, depth, activation)?; } Event::End(_) => { @@ -392,7 +407,9 @@ impl<'gc> E4XNode<'gc> { } Event::Text(bt) => { handle_text_cdata( - custom_unescape(bt, parser.decoder())?.as_bytes(), + custom_unescape(bt, parser.decoder()) + .map_err(|_| malformed_element(activation))? + .as_bytes(), ignore_white, &mut open_tags, &mut top_level, @@ -419,7 +436,8 @@ impl<'gc> E4XNode<'gc> { { continue; } - let text = custom_unescape(bt, parser.decoder())?; + let text = custom_unescape(bt, parser.decoder()) + .map_err(|_| malformed_element(activation))?; let text = AvmString::new_utf8_bytes(activation.context.gc_context, text.as_bytes()); let kind = match event { diff --git a/core/src/avm2/error.rs b/core/src/avm2/error.rs index 2e44622bc..a69939572 100644 --- a/core/src/avm2/error.rs +++ b/core/src/avm2/error.rs @@ -305,11 +305,3 @@ impl<'gc> From for Error<'gc> { Error::RustError(val.into()) } } - -// TODO - Remove this, and convert `quick_xml` errors into AVM errors, -// specific to the XML method that was original invoked. -impl<'gc> From for Error<'gc> { - fn from(val: quick_xml::Error) -> Error<'gc> { - Error::RustError(val.into()) - } -} diff --git a/tests/tests/swfs/avm2/xml_ctor_from_tostring/Main.as b/tests/tests/swfs/avm2/xml_ctor_from_tostring/Main.as index 4554f3a79..33c55410d 100644 --- a/tests/tests/swfs/avm2/xml_ctor_from_tostring/Main.as +++ b/tests/tests/swfs/avm2/xml_ctor_from_tostring/Main.as @@ -69,6 +69,13 @@ trace("Caught error: " + e); trace(e.errorID); } + + try { + trace(new XML("