Skip to content

Head: find_nth_line_from_end function is buggy #7247

@karlmcdowall

Description

@karlmcdowall

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions