[Top][All Lists]

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

Re: [Help-bash] Performing quote removal on data

From: Maarten Billemont
Subject: Re: [Help-bash] Performing quote removal on data
Date: Wed, 28 May 2014 16:05:47 -0400

On May 28, 2014, at 3:40 PM, Greg Wooledge <address@hidden> wrote:

>>> On May 28, 2014 1:54 AM, "Maarten Billemont" <address@hidden> wrote:
>>>> Suppose you have a variable whose value contains bash-escapes and quotes,
>>>> and you need to perform the operations bash would perform on that string
>>>> to turn it into a literal word.
>>>> var=?foo\ bar/?
> Ugh, stupid quotes?

Sorry, disabled those, I hope!  var='foo\ bar/'

>>>> How would you proceed to get the literal ?foo bar/? out of that,
> eval
>>>> in a safe way (ie. perform just pathname expansion and quote removal,
>>>> maybe even word splitting but that taking into account the quoted
>>>> whitespace)?  Specifically, I do NOT want any risk of performing command
>>>> execution or any other expansions on the data (eg. ?foo $(rm -rf ~)/?
> Oh.  So you want to do an eval on user-supplied code, but you don't want
> to ever run any commands other than variable assignments?
> Maybe you could set resource limits in such a way that fork() would
> become impossible?  Might be OS-specific.  Make sure you either do so
> in a subshell, or that you have a way to restore the limits afterward.
> Short of modifying bash to add shopts to disable command substitutions
> at will, or writing a full-blown bash parser in bash, I don't think
> there's any other way to make eval-able code safe to eval.
> I actually think "shopt -s nocmdsubs" or similar might be a useful
> feature, but I won't try to implement it.  Also, there's still another
> problem: what prevents the malicious user from sticking "shopt -u ..."
> in front of the command substitution?  Then you'd need to make the
> "shopt -s nocmdsubs" irreversible, which means you'd still need to do
> it all in a subshell, and communicate the results back to the parent
> somehow.  It's quite a mess.
> (For that matter, if a "no forking" resource limit is reversible, then
> you have the same problem!  Ugh....)

I'd rather not rely on eval at all.  The behaviour I want is essentially the 
default bash pathname completion:

mkdir "dir 1"

- "dir" completes to "dir\ 1"
- "dir\ " completes to "dir\ 1"
- "di*" completes to "dir\ 1"
- "$(:)di" does not complete

man bash does not describe exactly what bash's default pathname completion 
does, but it looks like we're seeing quote removal, word splitting and then 
pathname expansion.

Since the goal is essentially to write a reliable programmable completion 
function, and that function needs to populate a COMPREPLY array based on the 
word that is being completed, it might be possible to avoid converting the word 
to be completed into a literal:

1. If we have a list of possible completions to filter with the word currently 
being completed, we can use this instead:

partial=${COMP_WORDS[COMP_CWORD]} # This contains the readline word currently 
being completed.
completions=( house ball printer school "school bus" ) # A list of eligible 
words for completion.
IFS=$'\n' read -r -d '' COMPREPLY < <(compgen -W "$(printf '%q ' 
"address@hidden")" "$partial") # holy crap, it really shouldn't have to be this 
hard to do it right!

2. If we do NOT have a list of possible completions but rather need the current 
word being completed to populate that list, we're in trouble.

2a. One such case is doing pathname completion, but here we can fall back to 
compgen -o bashdefault:

IFS=$'\n' read -r -d '' COMPREPLY < <(compgen -o bashdefault "$partial*") # 
notice the trailing *

Sadly though, while it completes "dir\ " into "dir 1" just fine, it does NOT 
complete "dir' " or "dir' '" into "dir 1".  Consistency?  Why would you want 

Notice also that compgen -o dirnames "$partial" can be used to complete "dir' 
'" into "dir 1" nicely, but that in turn does not support pathname expansion 
and also only works on dirs.  The similarly named -o filenames does not do the 
same for filenames (I couldn't actually reproduce any effect of -o filenames).

So on that note, how do I, in programmable completion, perform a simple, 
regular, default bash pathname completion without re-implementing quote removal 
in bash code?

— Maarten Billemont (lhunath) —
me: – business: http://www.lyndir.com

Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail

reply via email to

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