Skip to content

Boolean flags accept --flag=value, diverging from GNU (only df rejects it) #538

Description

@julesmcrt

Problem

builtins.FlagSet is a type alias for pflag.FlagSet. Every builtin that
registers boolean flags with BoolP/Bool inherits pflag's NoOptDefVal="true"
behavior, which accepts the explicit-value form: head --verbose=false file,
rm --force=false target, truncate --no-create=true file, etc.

GNU coreutils documents these as no-argument options and rejects the =value
form before touching any operand:

$ head --verbose=false file
head: option '--verbose' doesn't allow an argument
(exit 1)

We silently accept it. This is a GNU-compat divergence affecting ~25 builtins.

Existing precedent

df already solves this with private noArgBool / noArgSentinel (a NUL-byte
sentinel that's unforgeable through execve) + registerNoArgBool, plus a pentest
test asserting df --all=false is rejected. See builtins/df/df.go.

Proposed fix

  1. Promote noArgBool / noArgSentinel / registerNoArgBool from the df
    package into the shared builtins package.
  2. Migrate all builtins with boolean flags to the shared helper.
  3. Delete df's private copy.
  4. Add bash-comparison scenario coverage for the --flag=value rejection.

Affected builtins

cat, cd, cut, du, grep, head, help, ip, ls, ping, ps, pwd, read, rm, sed,
sort, ss, strings, tail, tr, truncate, uname, uniq, wc, xargs
(df already handled)

Context

Surfaced in #537 (rm builtin review). This issue
tracks the systemic migration for the rest.

Originally posted by @chatgpt-codex-connector[bot] in #537 (comment)

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

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