aboutsummaryrefslogtreecommitdiff
path: root/src/reader/parser/inside_opening_tag.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/reader/parser/inside_opening_tag.rs')
-rw-r--r--src/reader/parser/inside_opening_tag.rs95
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))),
},
}
}