Skip to content

env: do not start a word for an unset variable in -S - #15877

Open
fixfon wants to merge 2 commits into
uutils:mainfrom
fixfon:fix/15773-env-split-unset-var
Open

fixfon wants to merge 2 commits into
uutils:mainfrom
fixfon:fix/15773-env-split-unset-var

Conversation

@fixfon

@fixfon fixfon commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

Fixes #15773

In env -S, a ${VAR} at the start of a word was handed to the unquoted state before the variable was looked up. If VAR was unset, nothing was added, but the word was already open, so an empty argument was pushed at the next blank, \_ or \c. env -S 'printf [%s] a ${U}' printed [a][], ${U}#c d no longer treated # as the start of a comment, and a command that began with an unset variable failed with an empty program name.

substitute_variable now returns whether the variable was set, and the delimiter state enters the unquoted state only in that case. An unset variable on its own adds no word, which matches the behavior described in the issue. Text next to the variable (x${U}, ${U}x), quoted forms ("${U}", ""${U}, ${U}"") and a variable that is set but empty behave as before.

I added unit tests for the split iterator (an unset variable on its own, and next to other text or quotes) and one test_env.rs test that checks the arguments with printf, so it does not need an external interpreter. The two tests for the bug fail on current main and pass with this change. cargo fmt, cargo clippy --all-targets -- -D warnings, cargo test -p uu_env and cargo test --test tests test_env pass. Tested on macOS only.

state_delimiter handed a leading ${VAR} to state_unquoted before the
variable was looked up, so an unset variable left an empty buffer that
was pushed as an empty argument. Let substitute_variable report whether
the variable was set and enter the unquoted state only in that case.

Fixes uutils#15773
Some(c) if ASCII_WHITESPACE_CHARS.contains(&c) => {
self.skip_one()?;
}
Some(DOLLAR) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add a short comment why: an unset variable must not start a word

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, added a short comment in c476c8f.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

env -S: unset variable becomes an empty argument, so perl runs stdin as code

2 participants