blaenk/hoedown

Calling read_to_end() on a Buffer object results in an infinite loop

Closed this issue · 3 comments

Example code:

extern crate hoedown;

use std::io;
use std::io::Read;


use hoedown::Render;

fn get_page() {
    let test_md = "# Hello world!\n\nHow are you?\n";
    let md_bytes: &[u8] = test_md.as_ref();

    let md = hoedown::Markdown::read_from(md_bytes);

    let mut html = hoedown::Html::new(hoedown::renderer::html::Flags::empty(), 0);
    let mut buffer = html.render(&md);
    {
        let b: &[u8] = buffer.as_ref();
        println!("Buffer length: {}", b.len())
    }
    // This hangs forever filling up bvec with an infinite number of copies of
    // the rendered HTML.
    let mut bvec = Vec::new();
    buffer.read_to_end(&mut bvec).unwrap();
    let bcurses = io::Cursor::new(bvec);
    println!("curses: {:?}", bcurses);
    // This works fine
    // let stringggggg = buffer.to_str().unwrap();
    // println!("Markdown is\n{}\n", stringggggg);
}

fn main() {
    println!("Starting...");

    get_page();
}

Thanks for bringing this up, I'm looking into it.

So I believe the problem is that the Read implementation for Buffer is incorrect because it essentially indirectly creates a new slice and delegates to its read(), which means we lose the read progress information across calls.

So I'm planning on removing it since it was a very basic implementation anyways, in which case you would simply get a slice of the buffer and use that as the Read type. Here's an example of how to do that in the regression test that I'm adding:

#[test]
fn test_read_to_end() {
    let buffer = Buffer::from("This is a test");
    let mut destination = Vec::new();

    timeout_ms(move || {
        let mut slice: &[u8] = &buffer;

        slice.read_to_end(&mut destination).unwrap();
    }, 1000);
}

Feel free to let me know if you have any other ideas or if that works for you.