diff options
Diffstat (limited to 'src/reader/parser/inside_opening_tag.rs')
-rw-r--r-- | src/reader/parser/inside_opening_tag.rs | 95 |
1 files changed, 51 insertions, 44 deletions
diff --git a/src/reader/parser/inside_opening_tag.rs b/src/reader/parser/inside_opening_tag.rs index b7f185a..fb6d001 100644 --- a/src/reader/parser/inside_opening_tag.rs +++ b/src/reader/parser/inside_opening_tag.rs @@ -9,6 +9,7 @@ use super::{OpeningTagSubstate, PullParser, QualifiedNameTarget, Result, State}; impl PullParser { pub fn inside_opening_tag(&mut self, t: Token, s: OpeningTagSubstate) -> Option<Result> { + let max_attrs = self.config.max_attributes; match s { OpeningTagSubstate::InsideName => self.read_qualified_name(t, QualifiedNameTarget::OpeningTagNameTarget, |this, token, name| { match name.prefix_ref() { @@ -30,20 +31,29 @@ impl PullParser { OpeningTagSubstate::InsideTag => match t { Token::TagEnd => self.emit_start_element(false), Token::EmptyTagEnd => self.emit_start_element(true), - Token::Character(c) if is_whitespace_char(c) => None, // skip whitespace + Token::Character(c) if is_whitespace_char(c) => None, // skip whitespace Token::Character(c) if is_name_start_char(c) => { + if self.buf.len() > self.config.max_name_length { + return Some(self.error(SyntaxError::ExceededConfiguredLimit)); + } self.buf.push(c); self.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::InsideAttributeName)) } - _ => Some(self.error(SyntaxError::UnexpectedTokenInOpeningTag(t))) + _ => Some(self.error(SyntaxError::UnexpectedTokenInOpeningTag(t))), }, OpeningTagSubstate::InsideAttributeName => self.read_qualified_name(t, QualifiedNameTarget::AttributeNameTarget, |this, token, name| { + // check that no attribute with such name is already present + // if there is one, XML is not well-formed + if this.data.attributes.contains(&name) { + return Some(this.error(SyntaxError::RedefinedAttribute(name.to_string().into()))) + } + this.data.attr_name = Some(name); match token { Token::EqualsSign => this.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::InsideAttributeValue)), Token::Character(c) if is_whitespace_char(c) => this.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::AfterAttributeName)), - _ => unreachable!() + _ => Some(this.error(SyntaxError::UnexpectedTokenInOpeningTag(t))) // likely unreachable } }), @@ -55,58 +65,55 @@ impl PullParser { OpeningTagSubstate::InsideAttributeValue => self.read_attribute_value(t, |this, value| { let name = this.data.take_attr_name()?; // will always succeed here - // check that no attribute with such name is already present - // if there is one, XML is not well-formed - if this.data.attributes.iter().any(|a| a.name == name) { // TODO: looks bad - // TODO: ideally this error should point to the beginning of the attribute, - // TODO: not the end of its value - Some(this.error(SyntaxError::RedefinedAttribute(name.to_string().into()))) - } else { - match name.prefix_ref() { - // declaring a new prefix; it is sufficient to check prefix only - // because "xmlns" prefix is reserved - Some(namespace::NS_XMLNS_PREFIX) => { - let ln = &*name.local_name; - if ln == namespace::NS_XMLNS_PREFIX { - Some(this.error(SyntaxError::CannotRedefineXmlnsPrefix)) - } else if ln == namespace::NS_XML_PREFIX && &*value != namespace::NS_XML_URI { - Some(this.error(SyntaxError::CannotRedefineXmlPrefix)) - } else if value.is_empty() { - Some(this.error(SyntaxError::CannotUndefinePrefix(ln.into()))) - } else { - this.nst.put(name.local_name.clone(), value); - this.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::AfterAttributeValue)) - } + match name.prefix_ref() { + // declaring a new prefix; it is sufficient to check prefix only + // because "xmlns" prefix is reserved + Some(namespace::NS_XMLNS_PREFIX) => { + let ln = &*name.local_name; + if ln == namespace::NS_XMLNS_PREFIX { + Some(this.error(SyntaxError::CannotRedefineXmlnsPrefix)) + } else if ln == namespace::NS_XML_PREFIX && &*value != namespace::NS_XML_URI { + Some(this.error(SyntaxError::CannotRedefineXmlPrefix)) + } else if value.is_empty() { + Some(this.error(SyntaxError::CannotUndefinePrefix(ln.into()))) + } else { + this.nst.put(name.local_name.clone(), value); + this.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::AfterAttributeValue)) } + } - // declaring default namespace - None if &*name.local_name == namespace::NS_XMLNS_PREFIX => - match &*value { - namespace::NS_XMLNS_PREFIX | namespace::NS_XML_PREFIX | namespace::NS_XML_URI | namespace::NS_XMLNS_URI => - Some(this.error(SyntaxError::InvalidDefaultNamespace(value.into()))), - _ => { - this.nst.put(namespace::NS_NO_PREFIX, value.clone()); - this.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::AfterAttributeValue)) - } - }, + // declaring default namespace + None if &*name.local_name == namespace::NS_XMLNS_PREFIX => + match &*value { + namespace::NS_XMLNS_PREFIX | namespace::NS_XML_PREFIX | namespace::NS_XML_URI | namespace::NS_XMLNS_URI => + Some(this.error(SyntaxError::InvalidDefaultNamespace(value.into()))), + _ => { + this.nst.put(namespace::NS_NO_PREFIX, value.clone()); + this.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::AfterAttributeValue)) + } + }, - // regular attribute - _ => { - this.data.attributes.push(OwnedAttribute { - name: name.clone(), - value - }); - this.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::AfterAttributeValue)) + // regular attribute + _ => { + if this.data.attributes.len() >= max_attrs { + return Some(this.error(SyntaxError::ExceededConfiguredLimit)); } + this.data.attributes.push(OwnedAttribute { + name, + value + }); + this.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::AfterAttributeValue)) } } }), OpeningTagSubstate::AfterAttributeValue => match t { - Token::Character(c) if is_whitespace_char(c) => self.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::InsideTag)), + Token::Character(c) if is_whitespace_char(c) => { + self.into_state_continue(State::InsideOpeningTag(OpeningTagSubstate::InsideTag)) + }, Token::TagEnd => self.emit_start_element(false), Token::EmptyTagEnd => self.emit_start_element(true), - _ => Some(self.error(SyntaxError::UnexpectedTokenInOpeningTag(t))) + _ => Some(self.error(SyntaxError::UnexpectedTokenInOpeningTag(t))), }, } } |