zsh-workers
 help / color / mirror / code / Atom feed
From: Oliver Kiddle <opk@zsh.org>
To: Bart Schaefer <schaefer@brasslantern.com>
Cc: Zsh hackers list <zsh-workers@zsh.org>
Subject: Re: [PATCH 1/3]: Add named references
Date: Thu, 09 Feb 2023 21:49:56 +0100	[thread overview]
Message-ID: <66045-1675975796.128039@FBF_.0yMO.Y8fk> (raw)
In-Reply-To: <CAH+w=7ZZUCqYe6w1ZqZZKR6iLsZH0SDDXyzwgTU93nxx6bmxjQ@mail.gmail.com>

Bart Schaefer wrote:
> My general feeling is to be ksh compatible where I don't think ksh is stupid.

Sounds reasonable.

> > It solves the problem of name clashes between a function and the calling
> > function.
>
> OK, so if
>   typeset ref
>   () { typeset -n ref=ref }
> works / is not a loop, then we don't need any other magic?

The following is similar:
  var=hello
  typeset -n ref
  () {
    typeset var=x
    ref=var
    echo $ref
  }
  typeset -p ref
  echo $ref

This creates a reference to a variable at a deeper local level. Ksh
prints "global reference cannot refer to local variable". With zsh's
dynamic scoping you could do the same thing with a reference that isn't
"global" but which has a scope that will outlast the variable. Making
var outlive the function is a feature you'd get with a reference
counting approach to namerefs. The best might be if ref returns to being
unset when the function returns but an error like ksh is fine too.

> I'm still not seeing that.  The writer of the caller of _call_function
> should know that it's a general rule that another function can't
> access a private variable.  Why would the writer pass a private name
> as an argument to any function, even a blackbox, if not expecting it
> to be referenced?  The rule for a private should be that you always
> pass its value.

I hadn't really thought about it that way, perhaps because ksh only
has private scoping and I'm used to writing in languages that only
have lexical scoping. Certainly if it is hard to implement, I have no
objection to this approach. It does have the big advantage of making the
whole uplevel question a non-issue. We do lose some orthogonality in
that you can use a private with builtins that take variable names like
read, compadd and printf (-v). Wrappers of those would have an added
limitation. (_approximate relies on a function wrapper of compadd so
privates can't be used with that)

When relying only on dynamic scoping, it would be good practice to
define all the namerefs to passed parameters as early as possible in a
function to reduce the risk of a name clash.

> Correct me if I still misunderstand, but I interpret the example above
> as implying that
>
>   f2() {
>     typeset -n ref=$1
>     # ... do stuff to $ref ...
>   }
>   f1() {
>     private var
>     f2 var
>   }
>
> should work just because the name is passed in a positional?  I would
> disagree with that on the grounds that you're making positionals into
> a special case, just a different kind of special case from ksh, that
> violates the intent of "private".

It isn't about the positionals being special but that it is useful to be
able to write a function that exposes an interface similar to read where
a variable can be named as a parameter. Ksh's making $1, $2.. special
on the rhs of typeset -n really is very ugly.

> The case I was asking about (and the only one I so far consider
> possibly viable) is
>
>   f1() {
>     private var
>     typeset -n ref=var
>     f2 ref
>   }

This puts the complexity into the caller so f2's interface is less
nice. And by needing ref as a local, f1 hasn't really benefitted from
var being able to be private. But if this is easy to implement then it
could be useful. If not, printing an error is fine too.

> Or perhaps you mean to be tagging on to your other suggestion and it would be
>   f2 \&var

My intention with that suggestion is that you'd only do that to refer to
$var from the scope of f1's caller. So in practice that'd sooner be
something like \&$3. For this, it'd be just `f2 var` and f2() would
declare `private -n mine=\&1`

> which feels like syntactic sugar for my example above, with the
> benefit of not needing to declare an extra parameter.  That's an
> interesting idea but I would not want this to work:

Again, the key difference is that the caller needed the extra parameter
where as using some sort of uplevel goes in the callee. You can't wrap
e.g. compadd transparently if the caller needs to change.

> With a hash that's just:
>
>   typeset -n ref
>   for ref in 'hash[(e)'${(k)^hash[(R)?*]}']'; do ...

"just"!?

> > And it could be wise to limit what can be done as part of the
> > subscript evaluation to avoid a CVE similar to the last one.
>
> validate_refname() is calling parse_subscript() ... would further
> examination of the accepted string be sufficient, or something more
> needed?  I think the greatest danger is of creating an infinite
> recursion, which can't really be caught in advance.

So if a function gets the target of a nameref from untrusted input the
function writer needs to know to validate it with something like

  [[ $var = [[:IDENT:]]## ]]

It might deprive us of many clever tricks but parse_subscript() could
gain a flag to disable anything questionable like command substitution
and math evaluation side-effects.

This should be an error perhaps:

  typeset -n ref=arr[1][2]

Currently it isn't possible to create a reference fo $!, $?, $@, $+, $#
and $$. If easy to add, there would be no harm in them.

And in 51388, Bart wrote:
> How about
>   can't change type via subscript reference
> ??

That sounds fine.

Oliver


  reply	other threads:[~2023-02-09 20:50 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-06  2:21 Bart Schaefer
2023-02-08  3:45 ` Oliver Kiddle
2023-02-08  4:59   ` Bart Schaefer
2023-02-08 23:16     ` Bart Schaefer
2023-02-09  0:47     ` Oliver Kiddle
2023-02-09  2:01       ` Oliver Kiddle
2023-02-09  5:45         ` Bart Schaefer
2023-02-09  4:49       ` Bart Schaefer
2023-02-09 20:49         ` Oliver Kiddle [this message]
2023-02-09 23:07           ` Bart Schaefer
2023-02-11  3:04             ` Bart Schaefer
2023-02-11  3:55               ` Bart Schaefer
2023-02-11  5:36                 ` Speaking of dangerous referents Bart Schaefer
2023-02-12  8:00                   ` Oliver Kiddle
2023-02-12  8:34                     ` Bart Schaefer
2023-02-11  7:02               ` [PATCH 1/3]: Add named references Oliver Kiddle
2023-02-11  7:45                 ` Bart Schaefer
2023-02-11 23:43                   ` Bart Schaefer
2023-02-11 23:45                     ` Bart Schaefer
2023-02-12  7:38                     ` Oliver Kiddle
2024-02-11  7:00                   ` Stephane Chazelas
2024-02-11 16:14                     ` Bart Schaefer
2024-02-11 16:42                       ` Bart Schaefer
2024-02-18  3:26                       ` Up-scope named references, vs. ksh Bart Schaefer
2024-02-20 21:05                         ` Stephane Chazelas
2024-02-20 22:30                           ` Bart Schaefer
2024-02-21 20:12                             ` Stephane Chazelas
2024-02-29  5:16                               ` Bart Schaefer
2024-03-01 18:22                                 ` Stephane Chazelas
2024-03-01 20:34                                   ` Bart Schaefer
2024-03-02  7:29                                     ` Bart Schaefer
2024-03-02 23:55                                       ` [PATCH] "typeset -nu" (was Re: Up-scope named references, vs. ksh) Bart Schaefer
2024-03-01 23:28                                   ` Up-scope named references, vs. ksh Bart Schaefer
2024-03-03 13:44                                     ` Stephane Chazelas
2024-03-03 19:04                                       ` Bart Schaefer
2024-03-03 20:27                                         ` Stephane Chazelas
2024-03-03 22:58                                           ` Bart Schaefer
2024-03-04 19:59                                             ` Stephane Chazelas
2024-03-05  1:05                                             ` Oliver Kiddle
2024-03-05  2:53                                               ` Bart Schaefer
2024-03-05  5:43                                                 ` Mikael Magnusson
2024-03-05  6:30                                                   ` Stephane Chazelas
2024-03-06  5:04                                                     ` [PATCH] local vs. nameref scoping (was Re: Up-scope named references, vs. ksh) Bart Schaefer
2023-02-12  9:02             ` [PATCH 1/3]: Add named references Oliver Kiddle
2023-02-12 18:59               ` Bart Schaefer
2023-02-12 19:45                 ` PM_* flags in zsh.h (was Re: [PATCH 1/3]: Add named references) Bart Schaefer
2023-02-12 21:01                   ` Oliver Kiddle
2023-02-12 22:54                 ` [PATCH 1/3]: Add named references Oliver Kiddle

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=66045-1675975796.128039@FBF_.0yMO.Y8fk \
    --to=opk@zsh.org \
    --cc=schaefer@brasslantern.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).