diff --git a/core/src/avm2/e4x.rs b/core/src/avm2/e4x.rs index e9adbeeaf..71bcbda13 100644 --- a/core/src/avm2/e4x.rs +++ b/core/src/avm2/e4x.rs @@ -407,8 +407,7 @@ impl<'gc> E4XNode<'gc> { match &event { Event::Start(bs) => { let child = - E4XNode::from_start_event(activation, &parser, bs, parser.decoder()) - .map_err(|_| malformed_element(activation))?; + E4XNode::from_start_event(activation, &parser, bs, parser.decoder())?; if let Some(current_tag) = open_tags.last_mut() { current_tag.append_child(activation.context.gc_context, child)?; @@ -416,8 +415,8 @@ impl<'gc> E4XNode<'gc> { open_tags.push(child); } Event::Empty(bs) => { - let node = E4XNode::from_start_event(activation, &parser, bs, parser.decoder()) - .map_err(|_| malformed_element(activation))?; + let node = + E4XNode::from_start_event(activation, &parser, bs, parser.decoder())?; push_childless_node(node, &mut open_tags, &mut top_level, activation)?; } Event::End(_) => { @@ -525,25 +524,41 @@ impl<'gc> E4XNode<'gc> { parser: &NsReader<&[u8]>, bs: &BytesStart<'_>, decoder: quick_xml::Decoder, - ) -> Result { + ) -> Result> { let mut attribute_nodes = Vec::new(); let attributes: Result, _> = bs.attributes().collect(); - for attribute in attributes? { + for attribute in attributes.map_err(|_| malformed_element(activation))? { let (ns, local_name) = parser.resolve_attribute(attribute.key); + let name = + AvmString::new_utf8_bytes(activation.context.gc_context, local_name.into_inner()); let namespace = match ns { ResolveResult::Bound(ns) => Some(AvmString::new_utf8_bytes( activation.context.gc_context, ns.into_inner(), )), ResolveResult::Unknown(ns) if ns == b"xmlns" => continue, - // TODO: Throw error on unknown prefix - _ => None, + // https://www.w3.org/TR/xml-names/#xmlReserved + // The prefix xml is by definition bound to the namespace name http://www.w3.org/XML/1998/namespace. + ResolveResult::Unknown(ns) if ns == b"xml" => { + Some("http://www.w3.org/XML/1998/namespace".into()) + } + ResolveResult::Unknown(ns) => { + return Err(Error::AvmError(type_error( + activation, + &format!( + "Error #1083: The prefix \"{}\" for element \"{}\" is not bound.", + String::from_utf8_lossy(&ns), + name + ), + 1083, + )?)) + } + ResolveResult::Unbound => None, }; - let name = - AvmString::new_utf8_bytes(activation.context.gc_context, local_name.into_inner()); - let value_str = custom_unescape(&attribute.value, decoder)?; + let value_str = custom_unescape(&attribute.value, decoder) + .map_err(|_| malformed_element(activation))?; let value = AvmString::new_utf8_bytes(activation.context.gc_context, value_str.as_bytes()); @@ -558,19 +573,30 @@ impl<'gc> E4XNode<'gc> { } let (ns, local_name) = parser.resolve_element(bs.name()); - + let name = + AvmString::new_utf8_bytes(activation.context.gc_context, local_name.into_inner()); let namespace = match ns { ResolveResult::Bound(ns) => Some(AvmString::new_utf8_bytes( activation.context.gc_context, ns.into_inner(), )), - // TODO: Throw error on unknown prefix - _ => None, + ResolveResult::Unknown(ns) if ns == b"xml" => { + Some("http://www.w3.org/XML/1998/namespace".into()) + } + ResolveResult::Unknown(ns) => { + return Err(Error::AvmError(type_error( + activation, + &format!( + "Error #1083: The prefix \"{}\" for element \"{}\" is not bound.", + String::from_utf8_lossy(&ns), + name + ), + 1083, + )?)) + } + ResolveResult::Unbound => None, }; - let name = - AvmString::new_utf8_bytes(activation.context.gc_context, local_name.into_inner()); - let data = E4XNodeData { parent: None, namespace, diff --git a/tests/tests/swfs/from_avmplus/as3/RuntimeErrors/Error1083XmlPrefixNotFound/test.toml b/tests/tests/swfs/from_avmplus/as3/RuntimeErrors/Error1083XmlPrefixNotFound/test.toml index 29f3cef79..cf6123969 100644 --- a/tests/tests/swfs/from_avmplus/as3/RuntimeErrors/Error1083XmlPrefixNotFound/test.toml +++ b/tests/tests/swfs/from_avmplus/as3/RuntimeErrors/Error1083XmlPrefixNotFound/test.toml @@ -1,2 +1 @@ num_ticks = 1 -known_failure = true diff --git a/tests/tests/swfs/from_avmplus/e4x/XML/kXMLPrefixNotBoundErr/test.toml b/tests/tests/swfs/from_avmplus/e4x/XML/kXMLPrefixNotBoundErr/test.toml index 29f3cef79..cf6123969 100644 --- a/tests/tests/swfs/from_avmplus/e4x/XML/kXMLPrefixNotBoundErr/test.toml +++ b/tests/tests/swfs/from_avmplus/e4x/XML/kXMLPrefixNotBoundErr/test.toml @@ -1,2 +1 @@ num_ticks = 1 -known_failure = true