-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Closed
Labels
Description
find_nth_line_from_end will generate the wrong offset if it has to search backwards more than 64K into the file (i.e. any searches bigger than the BUF_SIZE used in the code). Specifically, the problem is here...
fn find_nth_line_from_end<R>(input: &mut R, n: u64, separator: u8) -> std::io::Result<u64>
where
R: Read + Seek,
{
let size = input.seek(SeekFrom::End(0))?;
let mut buffer = [0u8; BUF_SIZE];
let buf_size: usize = (BUF_SIZE as u64).min(size).try_into().unwrap();
let buffer = &mut buffer[..buf_size];
let mut i = 0u64;
let mut lines = 0u64;
loop {
// the casts here are ok, `buffer.len()` should never be above a few k
**// The bug is here as it neglects that the input index is adjusted again at (*) below...**
input.seek(SeekFrom::Current(
-((buffer.len() as i64).min((size - i) as i64)),
))?;
input.read_exact(buffer)?; // (*)
for byte in buffer.iter().rev() {
if byte == &separator {
lines += 1;
}
// if it were just `n`,
if lines == n + 1 {
input.rewind()?;
return Ok(size - i);
}
i += 1;
}
if size - i == 0 {
input.rewind()?;
return Ok(0);
}
}
}I've got a fix on a dev branch, will put it up for PR shortly.
jfinkels