Skip to content

Commit

Permalink
Fix #514: always manage stack of names of opened / closed tags
Browse files Browse the repository at this point in the history
  • Loading branch information
Mingun authored and dralley committed Nov 28, 2022
1 parent c2ae68c commit 78a1cf5
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 21 deletions.
3 changes: 3 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
<B/>
<C/>
```
- [#514]: Fix wrong reporting `Error::EndEventMismatch` after disabling and enabling
`.check_end_names`

### Misc Changes

Expand Down Expand Up @@ -53,6 +55,7 @@

[#490]: https://github.com/tafia/quick-xml/pull/490
[#500]: https://github.com/tafia/quick-xml/issues/500
[#514]: https://github.com/tafia/quick-xml/issues/514
[XML name]: https://www.w3.org/TR/xml11/#NT-Name
[documentation]: https://docs.rs/quick-xml/0.27.0/quick_xml/de/index.html#difference-between-text-and-value-special-names

Expand Down
52 changes: 31 additions & 21 deletions src/reader/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,31 +142,40 @@ impl Parser {
} else {
&buf[1..]
};
if self.check_end_names {
let decoder = self.decoder();
let mismatch_err = |expected: String, found: &[u8], offset: &mut usize| {
*offset -= buf.len();
Err(Error::EndEventMismatch {
expected,
found: decoder.decode(found).unwrap_or_default().into_owned(),
})
};
match self.opened_starts.pop() {
Some(start) => {

let decoder = self.decoder();
let mismatch_err = |expected: String, found: &[u8], offset: &mut usize| {
*offset -= buf.len();
Err(Error::EndEventMismatch {
expected,
found: decoder.decode(found).unwrap_or_default().into_owned(),
})
};

// Get the index in self.opened_buffer of the name of the last opened tag
match self.opened_starts.pop() {
Some(start) => {
if self.check_end_names {
let expected = &self.opened_buffer[start..];
if name != expected {
let expected = decoder.decode(expected).unwrap_or_default().into_owned();
mismatch_err(expected, name, &mut self.offset)
} else {
// #513: In order to allow error recovery we should drop content of the buffer
self.opened_buffer.truncate(start);
Ok(Event::End(BytesEnd::wrap(name.into())))

return mismatch_err(expected, name, &mut self.offset);
}
}
None => mismatch_err("".to_string(), &buf[1..], &mut self.offset),

self.opened_buffer.truncate(start);
}
None => {
if self.check_end_names {
return mismatch_err("".to_string(), &buf[1..], &mut self.offset);
}
}
} else {
Ok(Event::End(BytesEnd::wrap(name.into())))
}

Ok(Event::End(BytesEnd::wrap(name.into())))
}

/// reads `BytesElement` starting with a `?`,
Expand Down Expand Up @@ -212,10 +221,11 @@ impl Parser {
Ok(Event::Empty(BytesStart::wrap(&buf[..len - 1], end)))
}
} else {
if self.check_end_names {
self.opened_starts.push(self.opened_buffer.len());
self.opened_buffer.extend(&buf[..name_end]);
}
// #514: Always store names event when .check_end_names == false,
// because checks can be temporary disabled and when they would be
// enabled, we should have that information
self.opened_starts.push(self.opened_buffer.len());
self.opened_buffer.extend(&buf[..name_end]);
Ok(Event::Start(BytesStart::wrap(buf, name_end)))
}
}
Expand Down

0 comments on commit 78a1cf5

Please sign in to comment.