Skip to content

cargo package does not truncate old file content #16683

@blyxxyz

Description

@blyxxyz

Problem

cargo package doesn't truncate any existing file content when writing a .crate file. If the new content of the file is shorter than the existing content then it will have trailing garbage.

Steps

$ cargo +nightly new trunc-repro -q
$ cd trunc-repro
$ dd if=/dev/urandom bs=100K count=1 status=none > file.bin
$ cargo +nightly package --allow-dirty
[...]
    Packaged 5 files, 101.0KiB (101.1KiB compressed)
[...]
$ rm file.bin
$ cargo +nightly package --allow-dirty
[...]
    Packaged 4 files, 1003B (716B compressed)
[...]
$ tar tf target/package/trunc-repro-0.1.0.crate

gzip: stdin: decompression OK, trailing garbage ignored
trunc-repro-0.1.0/Cargo.lock
trunc-repro-0.1.0/Cargo.toml
trunc-repro-0.1.0/Cargo.toml.orig
trunc-repro-0.1.0/src/main.rs
tar: Child returned status 2
tar: Error is not recoverable: exiting now
$ du -bh target/package/trunc-repro-0.1.0.crate
102K    target/package/trunc-repro-0.1.0.crate

Possible Solution(s)

I'm guessing this is the relevant part of the code:

let dst = artifact_dir.open_rw_exclusive_create(filename, ws.gctx(), "uplifted package")?;
src.file().seek(SeekFrom::Start(0))?;
std::io::copy(&mut src.file(), &mut dst.file())?;
let mut opts = OpenOptions::new();
opts.read(true).write(true).create(true);
let (path, f) = self.open(path.as_ref(), &opts, true)?;

It could open the file with truncate(true) or call set_len() either before or after writing.

Another part of the same module does call set_len(0) before writing:

dst.file().set_len(0)?;

Notes

There could be other features with the same problem, this is just the case that I hit.

Version

cargo 1.95.0-nightly (ce69df6f7 2026-02-12)
release: 1.95.0-nightly
commit-hash: ce69df6f72a3b6a2b5c722ba68ddef255344b31c
commit-date: 2026-02-12
host: x86_64-unknown-linux-gnu
libgit2: 1.9.2 (sys:0.20.4 vendored)
libcurl: 8.15.0-DEV (sys:0.4.83+curl-8.15.0 vendored ssl:OpenSSL/3.5.4)
ssl: OpenSSL 3.5.4 30 Sep 2025
os: Debian 13.0.0 (trixie) [64-bit]

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: bugS-acceptedStatus: Issue or feature is accepted, and has a team member available to help mentor or reviewregression-from-stable-to-stableRegression in stable that worked in a previous stable release.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions