avm2: Improve quick_xml to AVM2 XML error conversion

This commit is contained in:
Lord-McSweeney 2023-10-20 22:23:27 -07:00 committed by Lord-McSweeney
parent 4de186e18a
commit 5f217a6b9a
6 changed files with 52 additions and 19 deletions

View File

@ -5,9 +5,9 @@ use std::{
use gc_arena::{Collect, GcCell, Mutation}; use gc_arena::{Collect, GcCell, Mutation};
use quick_xml::{ use quick_xml::{
events::{BytesStart, Event}, events::{attributes::AttrError as XmlAttrError, BytesStart, Event},
name::ResolveResult, name::ResolveResult,
NsReader, Error as XmlError, NsReader,
}; };
use crate::{avm2::TObject, xml::custom_unescape}; use crate::{avm2::TObject, xml::custom_unescape};
@ -51,15 +51,51 @@ impl<'gc> Debug for E4XNodeData<'gc> {
} }
} }
fn malformed_element<'gc>(activation: &mut Activation<'_, 'gc>) -> Error<'gc> { fn make_xml_error<'gc>(activation: &mut Activation<'_, 'gc>, err: XmlError) -> Error<'gc> {
Error::AvmError( let error = match err {
type_error( XmlError::InvalidAttr(XmlAttrError::Duplicated(_, _)) => type_error(
activation,
"Error #1104: Attribute was already specified for element.",
1104,
),
XmlError::UnexpectedEof(currently_parsing) => match currently_parsing.as_str() {
"CData" => type_error(
activation,
"Error #1091: XML parser failure: Unterminated CDATA section.",
1091,
),
"DOCTYPE" => type_error(
activation,
"Error #1093: XML parser failure: Unterminated DOCTYPE declaration.",
1093,
),
"Comment" => type_error(
activation,
"Error #1094: XML parser failure: Unterminated comment.",
1094,
),
"XmlDecl" => type_error(
activation,
"Error #1097: XML parser failure: Unterminated processing instruction.",
1097,
),
_ => type_error(
activation, activation,
"Error #1090: XML parser failure: element is malformed.", "Error #1090: XML parser failure: element is malformed.",
1090, 1090,
) ),
.expect("Failed to construct XML TypeError"), },
) _ => type_error(
activation,
"Error #1090: XML parser failure: element is malformed.",
1090,
),
};
match error {
Ok(err) => Error::AvmError(err),
Err(err) => err,
}
} }
#[derive(Collect, Debug)] #[derive(Collect, Debug)]
@ -607,7 +643,7 @@ impl<'gc> E4XNode<'gc> {
loop { loop {
let event = parser let event = parser
.read_event() .read_event()
.map_err(|_| malformed_element(activation))?; .map_err(|e| make_xml_error(activation, e))?;
match &event { match &event {
Event::Start(bs) => { Event::Start(bs) => {
@ -633,7 +669,7 @@ impl<'gc> E4XNode<'gc> {
Event::Text(bt) => { Event::Text(bt) => {
handle_text_cdata( handle_text_cdata(
custom_unescape(bt, parser.decoder()) custom_unescape(bt, parser.decoder())
.map_err(|_| malformed_element(activation))? .map_err(|e| make_xml_error(activation, e))?
.as_bytes(), .as_bytes(),
ignore_white, ignore_white,
&mut open_tags, &mut open_tags,
@ -659,7 +695,7 @@ impl<'gc> E4XNode<'gc> {
continue; continue;
} }
let text = custom_unescape(bt, parser.decoder()) let text = custom_unescape(bt, parser.decoder())
.map_err(|_| malformed_element(activation))?; .map_err(|e| make_xml_error(activation, e))?;
let text = let text =
AvmString::new_utf8_bytes(activation.context.gc_context, text.as_bytes()); AvmString::new_utf8_bytes(activation.context.gc_context, text.as_bytes());
let node = E4XNode(GcCell::new( let node = E4XNode(GcCell::new(
@ -679,7 +715,7 @@ impl<'gc> E4XNode<'gc> {
continue; continue;
} }
let text = custom_unescape(bt, parser.decoder()) let text = custom_unescape(bt, parser.decoder())
.map_err(|_| malformed_element(activation))?; .map_err(|e| make_xml_error(activation, e))?;
let (name, value) = if let Some((name, value)) = text.split_once(' ') { let (name, value) = if let Some((name, value)) = text.split_once(' ') {
( (
AvmString::new_utf8_bytes( AvmString::new_utf8_bytes(
@ -733,7 +769,9 @@ impl<'gc> E4XNode<'gc> {
let mut attribute_nodes = Vec::new(); let mut attribute_nodes = Vec::new();
let attributes: Result<Vec<_>, _> = bs.attributes().collect(); let attributes: Result<Vec<_>, _> = bs.attributes().collect();
for attribute in attributes.map_err(|_| malformed_element(activation))? { for attribute in
attributes.map_err(|e| make_xml_error(activation, XmlError::InvalidAttr(e)))?
{
let (ns, local_name) = parser.resolve_attribute(attribute.key); let (ns, local_name) = parser.resolve_attribute(attribute.key);
let name = let name =
AvmString::new_utf8_bytes(activation.context.gc_context, local_name.into_inner()); AvmString::new_utf8_bytes(activation.context.gc_context, local_name.into_inner());
@ -763,7 +801,7 @@ impl<'gc> E4XNode<'gc> {
}; };
let value_str = custom_unescape(&attribute.value, decoder) let value_str = custom_unescape(&attribute.value, decoder)
.map_err(|_| malformed_element(activation))?; .map_err(|e| make_xml_error(activation, e))?;
let value = let value =
AvmString::new_utf8_bytes(activation.context.gc_context, value_str.as_bytes()); AvmString::new_utf8_bytes(activation.context.gc_context, value_str.as_bytes());

View File

@ -1,2 +1 @@
num_ticks = 1 num_ticks = 1
known_failure = true

View File

@ -1,2 +1 @@
num_ticks = 1 num_ticks = 1
known_failure = true

View File

@ -1,2 +1 @@
num_ticks = 1 num_ticks = 1
known_failure = true

View File

@ -1,2 +1 @@
num_ticks = 1 num_ticks = 1
known_failure = true

View File

@ -1,2 +1 @@
num_ticks = 1 num_ticks = 1
known_failure = true