Skip to content

Commit a86340b

Browse files
TptMingun
authored andcommitted
Fails on empty doctype
The parser was crashing with debug assertions enabled but passing with debug assertions disabled Closes #608
1 parent 358cc58 commit a86340b

File tree

4 files changed

+26
-6
lines changed

4 files changed

+26
-6
lines changed

Diff for: Changelog.md

+3
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,16 @@
2121
- [#603]: Fix a regression from [#581] that an XML comment or a processing
2222
instruction between a <!DOCTYPE> and the root element in the file brokes
2323
deserialization of structs by returning `DeError::ExpectedStart`
24+
- [#608]: Return a new error `Error::EmptyDocType` on empty doctype instead
25+
of crashing because of a debug assertion.
2426

2527
### Misc Changes
2628

2729
[#581]: https://github.com/tafia/quick-xml/pull/581
2830
[#601]: https://github.com/tafia/quick-xml/pull/601
2931
[#603]: https://github.com/tafia/quick-xml/pull/603
3032
[#606]: https://github.com/tafia/quick-xml/pull/606
33+
[#608]: https://github.com/tafia/quick-xml/issues/608
3134

3235

3336
## 0.28.2 -- 2023-04-12

Diff for: src/errors.rs

+5
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ pub enum Error {
3737
/// `Event::BytesDecl` must start with *version* attribute. Contains the attribute
3838
/// that was found or `None` if an xml declaration doesn't contain attributes.
3939
XmlDeclWithoutVersion(Option<String>),
40+
/// Empty `Event::DocType`. `<!doctype foo>` is correct but `<!doctype > is not.
41+
///
42+
/// See <https://www.w3.org/TR/xml11/#NT-doctypedecl>
43+
EmptyDocType,
4044
/// Attribute parsing error
4145
InvalidAttr(AttrError),
4246
/// Escape error
@@ -109,6 +113,7 @@ impl fmt::Display for Error {
109113
"XmlDecl must start with 'version' attribute, found {:?}",
110114
e
111115
),
116+
Error::EmptyDocType => write!(f, "DOCTYPE declaration must not be empty"),
112117
Error::InvalidAttr(e) => write!(f, "error while parsing attribute: {}", e),
113118
Error::EscapeError(e) => write!(f, "{}", e),
114119
Error::UnknownPrefix(prefix) => {

Diff for: src/reader/parser.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,9 @@ impl Parser {
117117
.iter()
118118
.position(|b| !is_whitespace(*b))
119119
.unwrap_or(len - 8);
120-
debug_assert!(start < len - 8, "DocType must have a name");
120+
if start + 8 >= len {
121+
return Err(Error::EmptyDocType);
122+
}
121123
Ok(Event::DocType(BytesText::wrap(
122124
&buf[8 + start..],
123125
self.decoder(),

Diff for: tests/fuzzing.rs

+15-5
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@
22
33
use quick_xml::events::Event;
44
use quick_xml::reader::Reader;
5-
use std::io::Cursor;
5+
use quick_xml::Error;
66

77
#[test]
88
fn fuzz_53() {
99
let data: &[u8] = b"\xe9\x00\x00\x00\x00\x00\x00\x00\x00\
1010
\x00\x00\x00\x00\n(\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\
1111
\x00<>\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<<\x00\x00\x00";
12-
let cursor = Cursor::new(data);
13-
let mut reader = Reader::from_reader(cursor);
12+
let mut reader = Reader::from_reader(data);
1413
let mut buf = vec![];
1514
loop {
1615
match reader.read_event_into(&mut buf) {
@@ -25,8 +24,7 @@ fn fuzz_101() {
2524
let data: &[u8] = b"\x00\x00<\x00\x00\x0a>&#44444444401?#\x0a413518\
2625
#\x0a\x0a\x0a;<:<)(<:\x0a\x0a\x0a\x0a;<:\x0a\x0a\
2726
<:\x0a\x0a\x0a\x0a\x0a<\x00*\x00\x00\x00\x00";
28-
let cursor = Cursor::new(data);
29-
let mut reader = Reader::from_reader(cursor);
27+
let mut reader = Reader::from_reader(data);
3028
let mut buf = vec![];
3129
loop {
3230
match reader.read_event_into(&mut buf) {
@@ -50,3 +48,15 @@ fn fuzz_101() {
5048
buf.clear();
5149
}
5250
}
51+
52+
#[test]
53+
fn fuzz_empty_doctype() {
54+
let data: &[u8] = b"<!doctype \n >";
55+
let mut reader = Reader::from_reader(data);
56+
let mut buf = Vec::new();
57+
assert!(matches!(
58+
reader.read_event_into(&mut buf).unwrap_err(),
59+
Error::EmptyDocType
60+
));
61+
assert_eq!(reader.read_event_into(&mut buf).unwrap(), Event::Eof);
62+
}

0 commit comments

Comments
 (0)