rust-syndication / rss

Library for serializing the RSS web content syndication format
https://crates.io/crates/rss
Apache License 2.0
419 stars 52 forks source link

Err when reading/writing/reading a channel #119

Closed ZNielsen closed 3 years ago

ZNielsen commented 3 years ago

rss does not properly escape all fields when reading an rss channel. As a result, writing an rss channel to a file, then reading back causes an Err.

Requesting channels are properly escaped on read/write.

Problem is reproducible in the program below. Errors with:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Xml(EscapeError(UnterminatedEntity(25..38)))', src/main.rs:33:37
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
fn main() {
    let test_file = std::path::PathBuf::from("/tmp/rss_test_file.rss");

    let mut enclosure = rss::Enclosure::default();
    // Escape the `&` when setting the URL
    enclosure.set_url("http://example.com?test=1&another=true".to_owned());

    let mut item = rss::Item::default();
    item.set_title("Test Item".to_owned());
    item.set_enclosure(Some(enclosure));

    let mut rss = rss::Channel::default();
    rss.set_title("Test RSS".to_owned());
    rss.set_items(vec![item]);

    // Write new rss to file
    let out_file = std::fs::File::create(&test_file).unwrap();
    rss.pretty_write_to(out_file, 38, 2).unwrap();

    // Read it back. All good so far
    let in_file = std::fs::File::open(&test_file).unwrap();
    let in_buf = std::io::BufReader::new(in_file);
    let rss = rss::Channel::read_from(in_buf).unwrap();

    // Write back out, may have changed something, may not have
    let out_file = std::fs::File::create(&test_file).unwrap();
    rss.pretty_write_to(out_file, 38, 2).unwrap();

    // Read it back again.
    let in_file = std::fs::File::open(&test_file).unwrap();
    let in_buf = std::io::BufReader::new(in_file);
    // This line will panic
    rss::Channel::read_from(in_buf).unwrap();
}