Date:        Wed, 09 Sep 2026 08:36:07 +0200 (CEST)
    From:        Jarle Greipsland <[email protected]>
    Message-ID:  <[email protected]>

  | I think the first "local" statement should be:
  |     local names="$1"
  | Otherwise the function might be tricked by maliciously
  | constructed file names.

You're right, it probably should, or
        local "names=$1"
which has the same effect.   Or just:
        local names; names=$1
That is, at least in our shell.

In the 2024 edition of POSIX, they invented something called a
"declaration utility" in which arguments that look like assignments
(an unquoted name, '=', and then any remainder of the word) are
parsed, and evaluated, as if they were assignment statements).
That is, among other things, the expansion doesn't happen until the
assignment is being processed, the whole "looks like an assignment"
arg is treated just like a var-assign would be, and parsed that way.
In that world, the quotes would be unwanted, and certainly not necessary.

Our shell doesn't do that, that is, we have zero declaration utilities
(not even the ones POSIX in their "wisdom" decided should have that
status, like "export" and "readonly") and probably never will, there is no
reason to do it, as except in shells with arrays, where there is a
desire to be able to do something like

        local var=(a b c)

without that turning into a syntax error, and where you can't
just quote the value, as then it wouldn't be an array constant
on the right, it would be a string instead; no changes are required.

We have no arrays, and never will as long as I'm involved (if a
new data type ever needed adding, it would be a list, not an array)
so no need of that kind of value, and hence no need for any special
parsing tricks.    The whole declaration utility thing is unnecessary,
adds bloat (complicates the parser), and achieves nothing that can't
easily be accomplished other ways

But, while you're right, in the actual function, and its planned usage,
it really makes no difference.

As the function is doing

        set -- $names

(unquoted, and it has to be) any tricks the caller might try to do
would work just as well (or better) there, than in the local statement,
where it is difficult to do much more than just be a nuisance.   The
expansion can't create syntax, just alter the actual args passed to
the local command from what was intended, which will either cause it
to generate an error, if the args aren't what is valid for the local
command (they can't be options, as the "name=" ends that possibility),
or it can cause a few more variables to be created local in the function
if they happen to have the correct format, which (here at least) would
be harmless.

But that set statement changes everything - any function doing something
like that is only ever intended to be called by very specifically planned
code, with a very specific form of known arg, never with anything that can
be influenced by the environment or user.  In this case it is intended to
expand patterns, looking for a group of files in a directory, and then
making sure that those file names don't violate whatever restriction that
wants or needs to be imposed - here, just that they have no single quote
characters in their names.  So it would always be called that way.  No
opportunity for weird args.

If you're imagining someone grabbing that function from somewhere, and
using it an unintended way - why would they bother?   If you want a function
which does weird things when you call it, just write the function that you
want, and call that one instead - you can achieve whatever results you
desire that way.

kre

ps: The one thing quoting would guard against is the existence of a file,
or files, named "names=something.jpg" in the current directory, which would
alter the way the function works slightly, but really, I believe, just
restricting the files selected from what was intended, to just those
starting with "names=" -- perhaps some very clever file naming in the
directory could make that do even weirder things.


Reply via email to