Skip to content

Quote "$@" throughout the shift script (#1081)#1085

Open
dduugg wants to merge 1 commit into
shift-org:mainfrom
dduugg:issue-1081-shift-quoting
Open

Quote "$@" throughout the shift script (#1081)#1085
dduugg wants to merge 1 commit into
shift-org:mainfrom
dduugg:issue-1081-shift-quoting

Conversation

@dduugg

@dduugg dduugg commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Fixes #1081.

Every ./shift subcommand that forwards arguments used an unquoted $@, at each hop of the call chain (dispatcher -> sub_* -> sub_compose -> docker). shift is a bash script, and unquoted $@ in bash re-splits each argument on whitespace and then glob-expands the results.

The most visible casualty is ./shift mysql -e "<sql>", which never runs the SQL and instead prints mysql's usage text, because the SQL string is split into many arguments before mysql sees it.

The change

Quote "$@" at all 18 forwarding sites (the dispatcher, sub_compose, and every sub_* that passes arguments through). The space-free service names that the other subcommands take (./shift logs node, ./shift down) are unaffected.

Scope is limited to the $@ word-splitting bug. The ${MYSQL_USER} / ${MYSQL_DATABASE} values on the mysql lines are controlled and space-free, so they are left as-is to keep the diff focused.

Verification

Driving the actual script with a stubbed docker on PATH, so the arguments that would reach docker compose can be counted. Argument used: -e "SELECT * FROM calevent WHERE title = 'a b';" (a glob and a space, the two failure modes):

fixed (this branch):    docker received 14 args
  ...
  [12] -e
  [13] SELECT * FROM calevent WHERE title = 'a b';        <- one intact argument

old (upstream/main):    docker received 42 args
  ...
  [13] SELECT
  [14] app                                                <- the * expanded to the repo listing
  [15] backend
  ... ( every file in the repo ) ...
  [40] 'a                                                 <- the space split the value
  [41] b';

Ordinary subcommands still pass their arguments correctly (./shift logs node -> compose logs --tail=50 -f node; ./shift down -> compose down), and the unknown-subcommand error path (exit 127) still fires. bash -n shift parses clean.

This bug also bit the verification steps originally written into #1077; the workaround there was to pipe SQL via ./shift mysql-pipe (stdin) instead of passing it as an argument.

Every subcommand that forwarded arguments used an unquoted $@, at
each hop of the call chain ( dispatcher -> sub_* -> sub_compose ->
docker ). Under bash that re-splits each argument on whitespace and
glob-expands it, so `./shift mysql -e "SELECT * FROM calevent"`
reached mysql as a dozen mangled tokens ( the * expanded to the repo
directory listing ), and mysql printed its usage text instead of
running the query.

Quote "$@" at every level so arguments with spaces or glob
characters pass through intact. No behavior change for the
space-free arguments the other subcommands take.
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.

Passing arguments to ./shift subcommands is broken by unquoted $@

1 participant