Skip to content

Commit

Permalink
Merge pull request #612 from Tpt/empty-doctype
Browse files Browse the repository at this point in the history
Return an error on empty doctype
  • Loading branch information
Mingun committed Jun 11, 2023
2 parents 358cc58 + a86340b commit 88a2f27
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 6 deletions.
3 changes: 3 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@
- [#603]: Fix a regression from [#581] that an XML comment or a processing
instruction between a <!DOCTYPE> and the root element in the file brokes
deserialization of structs by returning `DeError::ExpectedStart`
- [#608]: Return a new error `Error::EmptyDocType` on empty doctype instead
of crashing because of a debug assertion.

### Misc Changes

[#581]: https://github.com/tafia/quick-xml/pull/581
[#601]: https://github.com/tafia/quick-xml/pull/601
[#603]: https://github.com/tafia/quick-xml/pull/603
[#606]: https://github.com/tafia/quick-xml/pull/606
[#608]: https://github.com/tafia/quick-xml/issues/608


## 0.28.2 -- 2023-04-12
Expand Down
5 changes: 5 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ pub enum Error {
/// `Event::BytesDecl` must start with *version* attribute. Contains the attribute
/// that was found or `None` if an xml declaration doesn't contain attributes.
XmlDeclWithoutVersion(Option<String>),
/// Empty `Event::DocType`. `<!doctype foo>` is correct but `<!doctype > is not.
///
/// See <https://www.w3.org/TR/xml11/#NT-doctypedecl>
EmptyDocType,
/// Attribute parsing error
InvalidAttr(AttrError),
/// Escape error
Expand Down Expand Up @@ -109,6 +113,7 @@ impl fmt::Display for Error {
"XmlDecl must start with 'version' attribute, found {:?}",
e
),
Error::EmptyDocType => write!(f, "DOCTYPE declaration must not be empty"),
Error::InvalidAttr(e) => write!(f, "error while parsing attribute: {}", e),
Error::EscapeError(e) => write!(f, "{}", e),
Error::UnknownPrefix(prefix) => {
Expand Down
4 changes: 3 additions & 1 deletion src/reader/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,9 @@ impl Parser {
.iter()
.position(|b| !is_whitespace(*b))
.unwrap_or(len - 8);
debug_assert!(start < len - 8, "DocType must have a name");
if start + 8 >= len {
return Err(Error::EmptyDocType);
}
Ok(Event::DocType(BytesText::wrap(
&buf[8 + start..],
self.decoder(),
Expand Down
20 changes: 15 additions & 5 deletions tests/fuzzing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@

use quick_xml::events::Event;
use quick_xml::reader::Reader;
use std::io::Cursor;
use quick_xml::Error;

#[test]
fn fuzz_53() {
let data: &[u8] = b"\xe9\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\n(\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\
\x00<>\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<<\x00\x00\x00";
let cursor = Cursor::new(data);
let mut reader = Reader::from_reader(cursor);
let mut reader = Reader::from_reader(data);
let mut buf = vec![];
loop {
match reader.read_event_into(&mut buf) {
Expand All @@ -25,8 +24,7 @@ fn fuzz_101() {
let data: &[u8] = b"\x00\x00<\x00\x00\x0a>&#44444444401?#\x0a413518\
#\x0a\x0a\x0a;<:<)(<:\x0a\x0a\x0a\x0a;<:\x0a\x0a\
<:\x0a\x0a\x0a\x0a\x0a<\x00*\x00\x00\x00\x00";
let cursor = Cursor::new(data);
let mut reader = Reader::from_reader(cursor);
let mut reader = Reader::from_reader(data);
let mut buf = vec![];
loop {
match reader.read_event_into(&mut buf) {
Expand All @@ -50,3 +48,15 @@ fn fuzz_101() {
buf.clear();
}
}

#[test]
fn fuzz_empty_doctype() {
let data: &[u8] = b"<!doctype \n >";
let mut reader = Reader::from_reader(data);
let mut buf = Vec::new();
assert!(matches!(
reader.read_event_into(&mut buf).unwrap_err(),
Error::EmptyDocType
));
assert_eq!(reader.read_event_into(&mut buf).unwrap(), Event::Eof);
}

0 comments on commit 88a2f27

Please sign in to comment.