uutils / uutils/coreutils

cp: --sparse=always hangs if the source is truncated mid-copy

Open Beginner friendly
#12,648 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

U - cp
Dominant language
Rust
Stars
24.1k
Forks
2k
Avg merge
1d 5h
Merged PRs (30d)
365

Description

The copy loop in sparse_copy() (src/uu/cp/src/platform/linux.rs) advances only by the bytes read and never handles a zero-byte read:

while current_offset < size {
    let this_read = src_file.read(&mut buf)?;
    ...
    current_offset += this_read;
}

size is captured once from the initial metadata(). If the source shrinks afterwards, read() hits EOF and returns 0 before current_offset reaches size, so the loop spins forever at 100% CPU.

Steps to reproduce
$ truncate -s 2G big
$ ( sleep 0.2; truncate -s 0 big ) &      # shrink the source mid-copy
$ cp --reflink=never --sparse=always big copy
# never returns; cp pins a core. Interrupt with Ctrl-C.

It's a race window, so adjust the sleep / size if it completes; with a larger source it's easy to hit. GNU cp finishes.

Expected

cp stops at EOF instead of looping forever.


Reported by V12 (finding F-65898).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/uu/cp/src/platform/linux.rs at sparse_copy() and run the provided truncate-based reproducer. Verify that a source truncated during --sparse=always copying reaches EOF and exits instead of spinning, then exercise the relevant copy path with a regression check for this race.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
cli
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.