Skip to content

tail panics (aborts) on -c +N with a very large N (seek .unwrap() on EINVAL) #13887

Description

@leeewee

tail -c +N FILE seeks to byte N-1 of the file via file.seek(SeekFrom::Start(*count - 1)).unwrap().

FilterMode::Bytes(Signum::Positive(count)) if count > &1 => {
// GNU `tail` seems to index bytes and lines starting at 1, not
// at 0. It seems to treat `+0` and `+1` as the same thing.
file.seek(SeekFrom::Start(*count - 1)).unwrap();
}

When N-1 exceeds the filesystem's maximum seekable offset (on ext4, (2³²−1)×4096 = 17,592,186,040,320) — or, for any offset above i64::MAX, always — the underlying lseek fails with EINVAL and the .unwrap() aborts the process (panic=abort → SIGABRT, exit 134).
The site only executes when the input is a regular seekable file larger than sane_blksize (~4 KiB).

$ yes | head -c 8192 > big          # any regular file > sane_blksize (~4 KiB)

$ tail -c +17592186040322 big
thread 'main' panicked at src/uu/tail/src/tail.rs:483:52:
called `Result::unwrap()` on an `Err` value: Os { code: 22, kind: InvalidInput, message: "Invalid argument" }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Aborted (core dumped)
$ echo $?
134

$ tail -c +18446744073709551615 big
thread 'main' panicked at src/uu/tail/src/tail.rs:483:52:
called `Result::unwrap()` on an `Err` value: Os { code: 22, kind: InvalidInput, message: "Invalid argument" }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Aborted (core dumped)
$ echo $?
134

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