github uutils/coreutils 0.9.0

5 hours ago

Rust Coreutils 0.9.0 Release:

We are excited to announce the release of Rust Coreutils 0.9.0 - a release focused on safety and security. This cycle was shaped by a third-party security audit, driving extensive TOCTOU hardening and a sustained, project-wide effort to shrink the amount of unsafe code by removing it outright and migrating low-level syscalls from nix/libc to rustix. On top of that, we landed major zero-copy I/O performance work (splice/tee/pipe), broadened WebAssembly, Cygwin and Windows support, and continued contributing tests and bug reports upstream to GNU coreutils.


GNU Test Suite Compatibility:

Result 0.8.0 0.9.0 Change 0.8.0 to 0.9.0 % Total 0.8.0 % Total 0.9.0 % Change 0.8.0 to 0.9.0
Pass 630 625 -5 94.74% 90.58% -4.16%
Skip 14 8 -6 2.11% 1.16% -0.95%
Fail 21 56 +35 3.16% 8.12% +4.96%
Error 0 1 +1 0% 0.14% +0.14%
Total 665 690 +25 (new tests)

Note: The rise in failing tests is due to the upstream GNU test suite being extended, not to regressions on our side. We updated our GNU reference from 9.10 to 9.11 (PR #11922), which added 25 new tests (665 → 690). Many of these newly-introduced tests are not yet passing, which accounts for the jump from 21 to 56 failures; no previously-passing functionality regressed, and work is ongoing to address the new tests.


GNU testsuite evolution


Highlights:

  • Security Hardening (Zellic audit)

    • A third-party security audit by Zellic reviewed the codebase; the findings - widely reported as 44 CVEs (see also the Ubuntu update and the corrode write-up Bugs Rust won't catch) - were concentrated in TOCTOU races and filesystem edge cases that Rust's type system does not prevent
    • It's worth noting that many of these CVEs are not memory-safety issues but differences in behavior from GNU coreutils that the audit identified; aligning our semantics with GNU resolves them
    • This release closes many of them: a new TOCTOU-resistant uucore::safe_copy module; TOCTOU fixes in cp, mv, and chmod recursive traversal; rm dot/dotdot path-parsing protection; nohup.out now created with mode 0600; and chroot now resolves all ids before chrooting
  • Reducing unsafe & migrating to rustix

    • A sustained, project-wide push to shrink the unsafe surface: dozens of unsafe removals across utilities, tests, fuzz targets and uucore (get_groups, make_fifo, build.rs, and more)
    • Migration from nix/libc to rustix across id, tr, timeout, sort, wc, tail, cp, who, factor, and core process/IO paths
  • Performance

    • splice()/tee()/pipe() fast paths landed across cat, wc, head, tail, yes, cp, tee, and unexpand (e.g. unexpand +7.5%, faster cp from a pipe on Linux, tee via raw syscalls, yes using the tee syscall)
    • Consolidated in a reworked uucore::pipes / buf_copy
  • GNU Compatibility & Upstream Collaboration

    • Reference bumped to GNU 9.11, which extended the suite with 25 new tests (the reason the failure count went up - see the note above; it is not a regression)
    • We continue to contribute tests and bug reports upstream to GNU coreutils, and our compatibility work keeps surfacing edge cases on both sides
    • New fixes across numfmt, date, tr, cksum, factor, head, stat, and sort
  • numfmt Overhaul

    • Precision handling, rejection of scientific notation, LC_NUMERIC decimal separator, zero-padding for negative numbers, IEC precision cap, large %f values, --to=auto exit code, and multi-byte --suffix width accounting
  • ls Improvements

    • ls -lF symlink target indicators, link-count column no longer inflated per-ACL-file, version-sorting and recursive-mode fixes, independent permissions-column width
    • Refactor letting crate users (e.g. nushell) call ls without writing everything to stdout
  • Cross-platform Reach

    • WASI/wasm support for ln, dd, mktemp, and tty.wasm; Cygwin CI and builds (date, stdbuf); Windows tty (incl. msys2 paths); OpenBSD triage improvements
  • Internationalization

    • numfmt and du now honor LC_NUMERIC for the decimal separator
  • Contributions: This release was made possible by 30 new contributors joining our community


Call to Action:

Try it in your browser - Online Playground powered by WebAssembly
Help us translate - Contribute to Rust Coreutils on Weblate
Sponsor us on GitHub to accelerate development: github.com/sponsors/uutils

What's Changed

cat

chroot

cksum

  • cksum: fix parsing error with tagged cheksum files by @frenchua in #11704
  • cksum: get rid of print! and println! to avoid panicking on write errors by @RenjiSann in #12099
  • cksum: Fix --check filename escaping for 9.11 by @RenjiSann in #12156
  • cksum: Introduce HashLength newtype to avoid byte/bit misuse by @RenjiSann in #12235

coreutils

  • coreutils: --help args is same with --help by @oech3 in #11367
  • coreutils: fix panic on linux < 6.4 when /proc is not mounted by @oech3 in #12104

cp

date

  • date: replace regex with hand-written format spec parser by @sylvestre in #11758
  • date: use cfg unix by @oech3 in #11952
  • date: width prefix in %N format specifier is ignored ( %3N, %6N always output full 9 nanosecond digits) #12001 by @Devel08 in #12010
  • date: fix build for cygwin by @oech3 in #12309
  • date: re-zone trailing TZ abbreviation input to local timezone by @0xSoftBoi in #12327

dd

df

  • df: get rid of unnecessary clone calls by @fogti in #12073

dirname

du

echo

env

  • tests(env): increase signal delivery delay to fix flaky macOS CI by @sylvestre in #11829

expr

factor

  • factor: emit GNU 9.11 'is not a valid positive integer' for stdin input by @sylvestre in #12137
  • factor: remove unsafe str::from_utf8_unchecked by @oech3 in #12142

fmt

head

id

install

  • fix(install): follow symlink components in destination path with -D by @abendrothj in #11505
  • install: update comments and tests after symlink follow behavior change by @Ecordonnier in #12475

join

ln

logname

  • fix(logname): return error exit code when there is an error by @rodrigost23 in #9313

ls

  • ls: drop #[allow(clippy::needless_bool)] by @oech3 in #11739
  • ls: fix link-count column inflating per ACL file by @sylvestre in #11781
  • refactor uu_ls so that crate users can call the ls without having to print everything to stdout by @fdncred in #9851
  • ls: restore WASI ".." metadata fallback in collect_directory_entries by @sylvestre in #11930
  • ls: use cfg unix by @oech3 in #11953
  • ls: fix comparisons in version sorting and recursive mode by @Alonely0 in #12108
  • ls: hide paths argument by @cakebaker in #12113
  • fix(ls): respect sorting when grouping directories; disambiguate size sorting properly by @Alonely0 in #12109
  • ls: use lines() instead of split('\n') in test by @cakebaker in #12154
  • ls: track permissions column width independently by @sylvestre in #12411
  • ls: ls -lF symlink target indicators by @joknarf in #11554
  • ls: simplify symlink target indicator logic by @sylvestre in #12508

md5sum

mkdir

  • mkdir: acl and permission inheritance with -p by @j5awry in #11931
  • mkdir: simplify umask shaping and add regression tests by @sylvestre in #12467

mknod

mktemp

more

mv

nl

nohup

nproc

  • nproc: Reject quota with some schedulers by @oech3 in #11173

numfmt

od

paste

pathchk

pinky

pr

  • pr: exit with code 1 if --column argument is zero by @Devel08 in #11750

realpath

rm

rmdir

shred

sort

  • fix(sort): always install SIGINT handler to ensure temp dir cleanup by @mattsu2020 in #11889
  • fix(sort): explicitly clean up temp directory in TmpDirWrapper::Drop by @mattsu2020 in #11888
  • Add sort_bench_merge benchmark for sort -m (merge) performance by @nonontb in #12022
  • sort: Fix inconsistent sort orderg under i18n-collator with equal sorting keys. by @ksgk1 in #12013
  • sort: add benchmark for locale UTF-8 sorting by @sylvestre in #12185
  • sort: replace nix feature resource with rustix by @xtqqczze in #12275
  • sort: remove nix from dep by @oech3 in #12378
  • fix(sort): reject leading '+' in numeric (-n) sort by @leno23 in #12350
  • sort: fix incorrect sort ordering/output corruption with long line inputs + add a test by @karlicoss in #12471

split

stat

stdbuf

  • stdbuf: support cross-platform building by @YumeYuka in #11609
  • stdbuf: build on Windows (depending on cygwin dll) by @oech3 in #12329

stty

sum

  • feat(sum): use larger buffer in bsd_sum and sysv_sum by @xtqqczze in #12391

sync

  • refactor(sync): DRY do_sync_with function by @hlsxx in #12033
  • refactor(sync): remove unnecessary files move by @hlsxx in #12485

tail

tee

timeout

touch

  • touch: add regression test for pre-epoch date on 32-bit by @sylvestre in #11817

tr

tty

unexpand

uniq

uptime

wc

who

yes

uucore

  • fix(uucore): fix build failure by @xtqqczze in #11729
  • uucore: simplify splice() by @oech3 in #11745
  • uucore: replace nix of buf_copy by rustix by @oech3 in #11765
  • uucore: replace nix of FS related parts by rustix by @oech3 in #11771
  • uucore: enable process feature of rustix by @cakebaker in #11792
  • fix(uucore): use is_dir() instead of exists() for locale path resolution by @mattsu2020 in #11851
  • cp, uucore: remove unused returned u64 by @oech3 in #11837
  • uucore: remove returned and unused usize by @oech3 in #11920
  • uucore: simplify fallback when splice failed by @oech3 in #11921
  • uucore: splice fast-path for head -c & preliminary for dd, tail, split by @oech3 in #11844
  • uucore: dedup code of unbounded splice with broker by @oech3 in #11928
  • pipes.rs: add debug_assert! for RAM usage by @oech3 in #11994
  • uucore, cat: move unbounded splice code by @oech3 in #12008
  • safe_traversal.rs: remove 1 unsafe by @oech3 in #12029
  • fix(fs): replace incorrect error handling with last_os_error by @xtqqczze in #12057
  • refactor(buf_copy): remove unused code by @xtqqczze in #12081
  • uucore: do not use Linux specific fn at tests by @oech3 in #12128
  • uucore: fix cfg attributes causing dead code warnings by @xtqqczze in #12192
  • pipes.rs: don't mix raw write and buffered write by @oech3 in #12195
  • uucore: remove dead code by @xtqqczze in #12223
  • uucore/build.rs: remove unsafe by @oech3 in #12237
  • uucore: remove unsafe get_groups by @oech3 in #12270
  • uucore/build.rs: small refactoring by @cakebaker in #12250
  • uucore: remove unsafe make_fifo by @oech3 in #12243
  • yes, uucore::pipes: merge pipe_with_size to pipe and catch fcntl err by @oech3 in #12285
  • process: replace getuid with rustix::process::getuid by @Franklin-Qi in #12094
  • buf_copy.rs: don't test a trivial io::copy wrapper by @oech3 in #12344
  • od, uucore: Allow reusing RawReader by @oech3 in #12385
  • uucore: upgrade md-5, sha1, sha2, sha3, digest to latest versions by @gabrielhnf in #12367
  • pipes.rs: simplify trait and match by @oech3 in #12397
  • buf_copy/linux.rs: drop unused trait by @oech3 in #12345
  • pipes.rs: simplify dev_null & remove crate name from comment by @oech3 in #12408
  • pipes.rs: simplify by io::copy & doc the case it cannot be used by @oech3 in #12415
  • pipes.rs: remove fcntl overhead from splice_unbounded by @oech3 in #12422
  • pipes.rs: avoid usage of bool by @oech3 in #12444
  • pipes.rs: add missing count on fallback by @oech3 in #12451
  • pipes.rs: deduplicate many cfg's by @oech3 in #12436
  • pipes.rs: dedup code by including fallback to splice_exact by @oech3 in #12472
  • pipes.rs: replace bool by Result<(),()> by @oech3 in #12454
  • buf_copy: remove thin wrapper & useless conversion by @oech3 in #12487
  • pipes.rs: alias std::io::Result<Result<(), ()>> by @oech3 in #12483
  • simplify uucore::pipes::send_n_bytes by @oech3 in #12491

Security

Code Quality & Cleanup

CI & Build

Documentation

Platform Support

Dependency Updates

  • chore(deps): update rust crate zip to v8.5.1 by @renovate[bot] in #11696
  • chore(deps): update rust crate selinux to v0.6.1 by @renovate[bot] in #11702
  • chore(deps): update rust crate ctor to 0.9.0 by @renovate[bot] in #11733
  • chore(deps): update actions/github-script action to v9 by @renovate[bot] in #11741
  • chore(deps): update rust crates by @xtqqczze in #11730
  • chore(deps): update rust crate clap_complete to v4.6.1 by @renovate[bot] in #11753
  • chore(deps): update vampire/setup-wsl action to v6.1.0 by @renovate[bot] in #11754
  • deps: unpin selinux rust crate by @xtqqczze in #11759
  • chore(deps): update softprops/action-gh-release action to v3 by @renovate[bot] in #11769
  • chore(deps): update rust crate similar to v3.1.0 by @renovate[bot] in #11768
  • chore(deps): update rust crate ctor to 0.10.0 by @renovate[bot] in #11786
  • deps: remove unused rust crate fluent-bundle by @xtqqczze in #11776
  • chore(deps): update rust crate clap_complete to v4.6.2 by @renovate[bot] in #11797
  • chore(deps): update rust crate rayon to v1.12.0 by @renovate[bot] in #11799
  • chore(deps): update rust crate clap to v4.6.1 by @renovate[bot] in #11845
  • chore(deps): update rust crate divan to v4.5.0 by @renovate[bot] in #11877
  • chore(deps): update astral-sh/ruff-action action to v4 by @renovate[bot] in #11863
  • chore(deps): update mozilla-actions/sccache-action action to v0.0.10 by @renovate[bot] in #11954
  • chore(deps): update rust crate ctor to v0.10.1 by @renovate[bot] in #11955
  • chore(deps): update rust crate jiff to v0.2.24 by @renovate[bot] in #11964
  • chore(deps): update rust crate data-encoding to v2.11.0 by @renovate[bot] in #11982
  • chore(deps): update rust crate data-encoding-macro to v0.1.20 by @renovate[bot] in #11981
  • chore(deps): update rust crate blake3 to v1.8.5 by @renovate[bot] in #11989
  • chore(deps): update rust crate sha3 to 0.10.9 by @xtqqczze in #11999
  • chore(deps): update rust crate zip to v8.6.0 by @renovate[bot] in #12000
  • chore(deps): update rust crate onig to v6.5.3 by @renovate[bot] in #12017
  • chore(deps): update rust crate clap_complete to v4.6.3 by @renovate[bot] in #12039
  • chore(deps): update rand crate to v0.8.6 by @xtqqczze in #12043
  • chore(deps): update dawidd6/action-download-artifact action to v21 by @renovate[bot] in #12054
  • chore(deps): update rust crate selinux to v0.6.2 by @renovate[bot] in #12066
  • chore(deps): update rust crate divan to v4.6.0 by @renovate[bot] in #12070
  • chore(deps): update rust crate ctor to 0.11.0 by @renovate[bot] in #12067
  • chore(deps): update rust crate string-interner to 0.20.0 by @xtqqczze in #12103
  • chore(deps): update rust crate ctor to 0.12.0 by @renovate[bot] in #12101
  • chore(deps): update rust crate kqueue-sys to v1.1.0 by @xtqqczze in #12141
  • chore(deps): update rust crate crc-catalog to 2.5.0 by @xtqqczze in #12151
  • chore(deps): update rust crate exacl to 0.13.0 by @renovate[bot] in #12158
  • Bump ctor & adapt to change by @cakebaker in #12132
  • chore(deps): update rust crate ctor to v1.0.2 by @renovate[bot] in #12179
  • chore(deps): update rust crate ctor to v1.0.3 by @renovate[bot] in #12187
  • chore(deps): update rust crate ctor to v1.0.4 by @renovate[bot] in #12203
  • chore(deps): update rust crate clap_complete to v4.6.4 by @renovate[bot] in #12216
  • bump nix and libc by @oech3 in #12233
  • chore(deps): update rust crate ctor to v1.0.5 by @renovate[bot] in #12239
  • chore(deps): update rust crate clap_complete to v4.6.5 by @renovate[bot] in #12245
  • chore(deps): update rust crate filetime to v0.2.29 by @renovate[bot] in #12201
  • chore(deps): update rust crate ctor to v1.0.6 by @renovate[bot] in #12347
  • chore(deps): update rust crate digest to v0.11.3 by @renovate[bot] in #12388
  • deps: remove unnecessary package fields by @xtqqczze in #11968
  • chore(deps): update rust crate divan to v4.7.0 by @renovate[bot] in #12441
  • chore(deps): update rust crate similar to v3.1.1 by @renovate[bot] in #12457
  • chore(deps): update rust crate jiff to v0.2.25 by @renovate[bot] in #12473
  • chore(deps): update rust crate jiff to v0.2.26 by @renovate[bot] in #12476
  • chore(deps): update rust crate jiff to v0.2.27 by @renovate[bot] in #12482
  • chore(deps): update rust crate memchr to v2.8.1 by @renovate[bot] in #12488
  • chore(deps): update rust crate ctor to v1.0.7 by @renovate[bot] in #12509
  • chore(deps): update rust crate jiff to v0.2.28 by @renovate[bot] in #12511

Version Management

New Contributors

Full Changelog: 0.8.0...0.9.0

Don't miss a new coreutils release

NewReleases is sending notifications on new releases.