uutils / uutils/coreutils

mode: comma-separated mode strings accept forms GNU rejects

Open
#14,421 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

Version

uutils/coreutils main at d1dd5f9, tested on 2026-09-07 (arm64 macOS) against GNU
coreutils 9.11.

Summary

GNU accepts either one bare octal mode or a comma-separated list of symbolic
clauses. It rejects any list containing an octal clause, and rejects empty
clauses. We accept both. chmod, mkdir, install, mkfifo and mknod are
affected, and two of them disagree with each other on the same input.

Reproduction

Octal inside a comma list — GNU errors, we accept:

mode        GNU chmod   ours    GNU mkdir   ours
644,u+x     error       744     error       744
u+x,644     error       644     error       644
a-w,644     error       644     error       644
644,644     error       644     error       644
g+s,755     error       755     error       755
755,g+s     error       2755    error       755

755,g+s also disagrees between our own utils: chmod applies setgid, mkdir
loses it at mkdir(2) (that part is #12709).

Empty clauses — GNU errors, and chmod happens to error, but the others accept:

mode        GNU     chmod   mkdir   install   mkfifo
''          error   error   777     000       666
'   '       error   error   777     000       666
',,'        error   error   777     000       666
'644,'      error   error   644     644       644
',644'      error   error   644     644       644
'u+x,,g+x'  error   error   777     110       776

a+x,u+x, g=u, u+7, u=7, 0 and 00 all agree, so the divergence is
specifically an octal clause inside a list, plus empty clauses.

Cause

There are two separate implementations of the same comma-list loop:

  • uucore::mode::parse_chmod (src/uucore/src/lib/features/mode.rs:322-351),
    used by mkdir, install, mkfifo and mknod. It skips empty clauses at
    mode.rs:338-340, which is why those four accept the second table.
  • chmod::calculate_new_mode (src/uu/chmod/src/chmod.rs:327-362), which
    reimplements the loop and does not skip empty clauses, so they reach
    parse_symbolic("") and error. chmod passing the second table is accidental,
    not intended.

Both dispatch per clause on "contains an ASCII digit, so treat it as numeric"
(mode.rs:342, chmod.rs:331). That is what allows an octal clause anywhere in
a list; GNU's grammar only allows a bare octal as the whole argument.

Impact

Mostly accepting invalid input rather than producing wrong permissions, but
install -m '' src dst exits 0 and leaves a mode 000 file, and mkdir -m ''
silently uses 0777 because the empty string leaves parse_chmod's starting
value untouched.

Suggested fix

Implement GNU's grammar once in uucore::mode: a bare octal accepted only as
the entire string, otherwise a non-empty list of symbolic clauses with empty
clauses rejected. Then delete chmod's duplicate loop and route it through the
same entry point, keeping its naive-mode/umask diagnostic behavior.

Note that five existing unit tests assert the current behavior and would need
removing rather than re-pinning: mode.rs:496, :534-535, :541-543,
:583-584, :591-594 — including a test_parse_mixed_numeric_and_symbolic
named after the incompatible form.

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 with uucore::mode::parse_chmod in src/uucore/src/lib/features/mode.rs and chmod::calculate_new_mode in src/uu/chmod/src/chmod.rs, then read the mode unit tests around the cited lines. Run the affected Rust tests before changing behavior. Done means the shared parsing follows the stated GNU grammar across chmod, mkdir, install, mkfifo and mknod, with incompatible tests removed or updated.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.