Repository: tafia/quick-xml
Pull request #135 (2018-09-13 19:53:35)

Fix minor bug for parsing comment tag
The following code terminates with panic `thread 'main' panicked at 'slice index starts at 6 but ends at 4', libcore/slice/mod.rs:1971:5`.

```rust
extern crate quick_xml;

use quick_xml::events::Event;
use quick_xml::Reader;

fn main() {
    let xml = "<a></a><!-->-->";
    let mut reader = Reader::from_str(&xml);
    reader.trim_text(true);
    let mut buf = Vec::new();
    loop {
        match reader.read_event(&mut buf) {
            Ok(Event::Comment(ref e)) => {
                println!("Comment: \"{}\"", reader.decode(e));
            }
            Ok(Event::Eof) => break,
            Err(e) => println!("Error: {:?}", e),
            _ => (),
        }
    }
}
```

tafia: Thanks for the fix!
Could you add a test to make sure it won't happen again?
Could you also run the latest version of rustfmt-preview on stable?
yawara: @tafia I added the test.

If I run rustfmt on stable, the codes which I don't write will be changed because stable rust 1.29 was released yesterday. 

Patch:
diff --git a/src/errors.rs b/src/errors.rs
index 2f1caf5..a6c3fc1 100644
--- a/src/errors.rs
+++ b/src/errors.rs
@@ -26,7 +26,10 @@ pub enum Error {
     #[fail(display = "Cannot read text, expecting Event::Text")]
     TextNotFound,
 
-    #[fail(display = "XmlDecl must start with 'version' attribute, found {:?}", _0)]
+    #[fail(
+        display = "XmlDecl must start with 'version' attribute, found {:?}",
+        _0
+    )]
     XmlDeclWithoutVersion(Option<String>),
 
     #[fail(
diff --git a/src/escape.rs b/src/escape.rs
index 890e442..965f47b 100644
--- a/src/escape.rs
+++ b/src/escape.rs
@@ -23,7 +23,8 @@ pub enum EscapeError {
     ),
 
     #[fail(
-        display = "Error while escaping character at range {:?}: Cannot find ';' after '&'", _0
+        display = "Error while escaping character at range {:?}: Cannot find ';' after '&'",
+        _0
     )]
     UnterminatedEntity(::std::ops::Range<usize>),
 
diff --git a/src/reader.rs b/src/reader.rs
index 52c10ba..8ab3149 100644
--- a/src/reader.rs
+++ b/src/reader.rs
@@ -308,7 +308,7 @@ impl<B: BufRead> Reader<B> {
         let len = buf.len();
         if len >= buf_start + 3 && &buf[buf_start + 1..buf_start + 3] == b"--" {
             let mut len = buf.len();
-            while len < 5 || &buf[len - 2..] != b"--" {
+            while (len - buf_start) < 5 || &buf[len - 2..] != b"--" {
                 buf.push(b'>');
                 match read_until(&mut self.reader, b'>', buf) {
                     Ok(0) => {
@@ -991,7 +991,6 @@ impl NamespaceBufferIndex {
                     .rev()
                     .find(|n| n.prefix(buffer) == prefix)
                     .map(|ns| (ns.opt_value(buffer), &value[1..]))
-            })
-            .unwrap_or((None, qname))
+            }).unwrap_or((None, qname))
     }
 }
diff --git a/src/writer.rs b/src/writer.rs
index 3c37dab..d8c225b 100644
--- a/src/writer.rs
+++ b/src/writer.rs
@@ -135,11 +135,10 @@ impl<W: Write> Writer<W> {
         let mut wrote = 0;
         if let Some(ref i) = self.indent {
             if i.should_line_break {
-                wrote = self.writer.write(b"\n").map_err(Error::Io)?
-                    + self
-                        .writer
-                        .write(&i.indents[..i.indents_len])
-                        .map_err(Error::Io)?;
+                wrote = self.writer.write(b"\n").map_err(Error::Io)? + self
+                    .writer
+                    .write(&i.indents[..i.indents_len])
+                    .map_err(Error::Io)?;
             }
         }
         Ok(wrote + self.write(before)? + self.write(value)? + self.write(after)?)


Test patch:
diff --git a/tests/test.rs b/tests/test.rs
index 70268f0..3713735 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -81,6 +81,21 @@ fn test_attribute_equal() {
     }
 }
 
+#[test]
+fn test_comment_starting_with_gt() {
+    let src = b"<a /><!-->-->";
+    let mut r = Reader::from_reader(src as &[u8]);
+    r.trim_text(true).expand_empty_elements(false);
+    let mut buf = Vec::new();
+    loop {
+        match r.read_event(&mut buf) {
+            Ok(Comment(ref e)) if &**e == b">" => break,
+            Ok(Eof) => panic!("Expecting Comment"),
+            _ => (),
+        }
+    }
+}
+
 /// Single empty element with qualified attributes.
 /// Empty element expansion: disabled
 /// The code path for namespace handling is slightly different for `Empty` vs. `Start+End`.
diff --git a/tests/xmlrs_reader_tests.rs b/tests/xmlrs_reader_tests.rs
index 623dc97..435473d 100644
--- a/tests/xmlrs_reader_tests.rs
+++ b/tests/xmlrs_reader_tests.rs
@@ -408,8 +408,7 @@ impl<'a> Iterator for SpecIter<'a> {
                 b' ' | b'\r' | b'\n' | b'\t' | b'|' | b':' => false,
                 b'0'...b'9' => false,
                 _ => true,
-            })
-            .unwrap_or(0);
+            }).unwrap_or(0);
         if let Some(p) = self.0.windows(2).position(|w| w == b")\n") {
             let (prev, next) = self.0.split_at(p + 1);
             self.0 = next;