bug-gnulib
[Top][All Lists]
Advanced

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

Re: gnupload: fix Shellcheck warnings


From: Eric Blake
Subject: Re: gnupload: fix Shellcheck warnings
Date: Wed, 28 Nov 2018 10:40:05 -0600
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.3.0

On 11/28/18 10:00 AM, Bruno Haible wrote:
Hi Ben,

This patch silences some warnings from Shellcheck, mostly about using
POSIX $(..) command substitutions instead of old backtick
substitutions.

The script starts with '#!/bin/sh'. /bin/sh on IRIX does not support
$(...). But I think no GNU maintainer is using IRIX on their development
machine. Therefore it's fine with me.

-  conf=`sed 's/#.*$//;/^$/d' "$conffile" | tr "\015$nl" '  '`
+  conf=$(sed 's/#.*$//;/^$/d' "$conffile" | tr "\\015$nl" '  ')

Is the interpretation of backslashes inside $(...) different than
inside `...`?

Yes. Inside ``, \ is an escape for $, `, and \; \ in front of anything else the \ is preserved literally, but may be subject to further interpretation according to the contents within ``. Inside $(), the normal shell grammar applies, and the closing ) is determined by whether you can parse the contents as a shell script. As a demonstration (using printf, since using echo has its own problems when an echo implementation also does backslash interpolation):

$ printf %s\\n `printf %s "\\\\"`
\
$ printf %s\\n $(printf %s "\\\\")
\\

Within ``, there are two \\ pairs flattened to \ before the shell parses the command to substitute; but parsing "\\" for the inner printf results in a single \ output. Within $(), there is no flattening before the shell parses the command to substitute, and parsing "\\\\" for the inner printf results in a doubled \ output.

Or:

$ printf %s\\n `printf %s "\\\"`
\

Well-formed - there is one \\ pair, flattened to \, while the third \ is followed by " so it is output literally, which means the inner parser sees "\\" which is well-formed, and results in a single \ output via printf.

$ printf %s\\n $(printf %s "\\\")
>

Here, the shell follows its normal parsing rules - it is looking for a closing ", because within "\\\"...., the first \\ pair is a single quoted \, the next \" is a quoted ", the ) and newline also part of the double-quoted string, and so on. Until you supply a closing " and then another ) to end the $() construct, the shell is waiting for more input to parse. Thus, conversion of `` to $() MUST be aware of any changed handling of \ present in the command substitution.


Or is this an independent fix?

Hard to say.  Note that:

printf %s "\015"
printf %s "\\015"

both output five bytes (single backslash, three digits, and a newline) - that's because in "", \ followed by an unknown character still outputs the \ verbatim. So the tr process is not seeing any change to its arguments - `"\015"` and $("\015") are the same as `"\\\\015"` and $("\\015") (the former two relying on the character after \ not being special and therefore the \ being used literally, the latter two being fully escaped to ensure that a single literal \ results). But switching between non-special form and fully-escaped form is odd, and should be done independently if at all - in general, the conversion from `` to $() should only ever remove \ that were special to `` but not needed for $(), and not ever need to add \.

--
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org



reply via email to

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