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: Mon, 24 May 2021 03:42:42 +0200
User-agent: Evolution 3.38.3-1

On Sat, 2021-05-22 at 08:23 +0900, Koichi Murase wrote:
> 
> First, one needs to understand that 1) there is also double
> unescaping
> here: quote removal by Bash and escape sequences of regular
> expressions.
Well that's what I'd expect from any regexpes, e.g. when I use them in
sed...

>  2) To complicate matters further, from Bash 3.2, the
> strings obtained by quote removal are again escaped for regular
> expressions so that they will be treated literally in the regex
> processing.
... I guess this kinda confused me though.


> - [\$\`\"\'\\] will be recognized as [<quoted $`"'\>] by Bash, and
> escaped for regular expressions as [$`"'\] (actually, there is no
> need
> of escaping because none of $`"'\ have special meaning in bracket
> expressions in ERE). Then, [$`"'\] will be passed to the regex
> engine.
Okay so I need to escape them once, for bash not taking their special
meaning, but don't need to escape them another time (for the ERE).

>From the bash manual I would have understood, that I even don't need
that first escaping, which kinda aligned with the fact that "..." the
whole thing didn't work, but actually required " in the string to be
matched.
I didn't realize then that:


> - It will be recognized as <quoted [$`\'"\]> by Bash, and then
> escaped
> as \[\$`\\'"\\\] before it is sent to the regex engine.

it does another round of escaping for patterns.


> - Oh, this example is interesting. I guess [\$\`\'\"\] is treated as
> [<quoted $`'"]> and "escaped" as [$`'"], but it's just a naive guess.

Hmm then I'd have expected a syntax error, as the bracket expression
isn't closed.



> Since it seems you care about various possible shopt settings, I
> recommend you to anytime store the regular expression in a variable
> and use that variable on the right-hand side of =~ operator. In this
> way, the regular expressions work the same for either side of "shopt
> -s/-u compat31"

Yes, and thanks for pointing me to that. I wouldn't have notice that
this setting affects the matching.


> But actually, in this case, we can actually simply use the glob
> pattern (operator ==) instead of regular expressions.
> 
> if [[ $str == *[\$\`\'\"\\]* ]]; then
> [...]

As far as I understand, this is *not* affected by compat31, right?!

I do like that more, because I don't have to use a temporary variable,
which has a hypothetical change to collide with something the user has
set or might be accidentally used later.

It would be nice if something like the local keyword could be used for
dot sourced files or things like when the shell loads .profile/.bashrc
and friends.


I guess the following would be equivalent (while avoiding the "bashism"
- which however doesn't really matter in my case, as I only target
.bashrc, which is anyway just bash):

[ -n "${str##*[\$\`\'\"\\]*}"  -o  -z "${str}" ] && echo "NO evil char" || echo 
"evil char"
or
[ -n "${str##*["$`'\"\\"]*}"  -o  -z "${str}" ] && echo "NO evil char" || echo 
"evil char"


> For safety (against code injection), I think excluding $ and ` is
> enough, but if one wants to get the same results with `promptvars'
> on/off, \ should also be excluded.

Hmm I was thinking about including ' and " because the manpage says:
> After the string is decoded, it is  expanded  via  parameter
> expansion, command substitution, arithmetic expansion,

> and quote removal


But I guess this applies only to the outer quotes of e.g.
PS1="...${str}..."
and not to the content of str, right?

So - correct me if I'm wrong - ultimately it would boil down to your:
   if [[ $str == *['$`\']* ]]; then
respectively
   if [ -n "${str##*['$`\']*}"  -o  -z "${str}" ]; then



Thanks a lot for your help so far!

Cheers,
Chris.




reply via email to

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