help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: how to (safely) escape an arbitrary string for use in PS1


From: Christoph Anton Mitterer
Subject: Re: how to (safely) escape an arbitrary string for use in PS1
Date: Fri, 21 May 2021 23:13:27 +0200
User-agent: Evolution 3.38.3-1

On Fri, 2021-05-21 at 07:44 +0900, Koichi Murase wrote:
> As I have mentioned, there are two unescaping. The first processing
> is
> \u to usernames, \$ to # or $, \\ to \, etc. The second processing
> (promptvars) includes \\ to \, \$ to $, \` to `, and \" to " as well
> as expansions of ${}, $(), $(()). You can understand it step-by-step.
Oh, so it (un)escapes \\ twice? Okay I didn't get that at first.
Seems odd, why does it do that?

Anyway,.. a bit sad, that this cannot be used safely in bash :-(





My next idea would have been to at least do the following:

a) *If* the string to be added to PS1 contains none of the "dangerous"
characters,... include it directly.

b) If it does, include the variable that contains the string (and let
it expand)... of course this would still break, if someone then turns
of promptvars.



For a) I played a bit around with what's better... match for all
characters which are safe, or match for all which are not.

All which are safe, could be something like (plus maybe a few more like
_ . and so on):
  [[ "$str" =~ ^[[:alnum:]]*$ ]]

where I think it wouldn't even matter, that this is subject to
nocasematch.

But the problem here is, that this still doesn't get much unicode and
that unicode even works only if a proper LC_CTYPE is active.
Even if I:
   ( LC_ALL=C.UTF-8; [[ "$str1" =~ ^[[:alnum:]]*$ ]]; echo $?)
that is set it explicitly in a subshell, there is no guarantee that the
locale is really there, and there doesn't seem to be any easily
catchable error, if it's not (there goes something so stderr, but the
actual test may still yield 0.



For b) I'd have done something like:
( shopt -u nocasematch ; LC_ALL=C ; [[ "$str" =~ [\$\`\'\"\\] ]] ) ; echo $?

which seems to work, but I don't fully understand why ^^

The shopt is probably irrelevant, cause I anyway match only characters
without case.
The LC_ALL is probably irrelevant, too.

What I don't understand:
- whether I use \$ or just $ in the bracket seems irrelevant
- if I put quotes around the whole regexp, like "[\$\`\'\"\\]" it
  doesn't work
- while bash manual says:
     "Bracket expressions in regular expressions must be treated
      carefully, since normal quoting characters lose their meanings
      between brackets."
  I seem to need to quote ' and " inside the bracket expression
- interestingly: [\$\`\'\"\] (i.e. not double-\ at the end ... does
  seem to be parsed, but doesn't match \ ... shouldn't that be a syntax
  error?

And the bigger question:
Which characters do I actually need to check for in order to be safe
(i.e. to determine whether an arbitrary string might be subject to any
expansions/substitutions/etc. and can thus not directly be used inside
PS1)?
- $ and ` are clear
- I guess I won't need to check for ( ) { } | ; & && || as there should
  be no pipes, subshells, etc. possible when PS1 is evaluated
- I'm not so sure about whether I need to check for \ ' "
  I've included them now cause I feel they seem evil ;-)

Anything else I should consider?



Thanks,
Chris.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]