[libvirt] [PATCH 2/3] Add virBufferEscapeShell
Eric Blake
eblake at redhat.com
Wed Oct 12 23:16:35 UTC 2011
On 10/12/2011 04:39 PM, Guido Günther wrote:
> Escape strings so they're safe to pass to the shell. Based on glib's
> g_quote_string.
Is this still true, or does it now resemble more what I did
(independently from g_quote_string) in tools/virsh.c cmdEcho?
> ---
> src/libvirt_private.syms | 1 +
> src/util/buf.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++
> src/util/buf.h | 1 +
> 3 files changed, 56 insertions(+), 0 deletions(-)
>
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 4f96518..862f3ac 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -29,6 +29,7 @@ virBufferEscape;
> virBufferEscapeSexpr;
> virBufferEscapeString;
> virBufferFreeAndReset;
> +virBufferEscapeShell;
Sort this line (up a couple).
> +++ b/src/util/buf.c
> @@ -486,6 +486,60 @@ virBufferURIEncodeString (virBufferPtr buf, const char *str)
> }
>
> /**
> + * virBufferEscapeShell:
> + * @buf: the buffer to append to
> + * @str: an unquoted string
> + *
> + * Quotes a string so that the shell (/bin/sh) will interpret the
> + * quoted string as unquoted_string.
> + */
> +void
> +virBufferEscapeShell(const virBufferPtr buf, const char *str)
We are modifying buf, so this should be "(virBufferPtr buf", not "(const
virBufferPtr buf" (I have another pending patch that tried to do this on
existing functions:
https://www.redhat.com/archives/libvir-list/2011-September/msg01255.html)
> +
> + len = strlen(str);
> + if (xalloc_oversized(4, len) ||
> + VIR_ALLOC_N(escaped, 4 * len + 3)< 0) {
> + virBufferSetError(buf);
Yay - conflict resolution fun for whichever of our two series gets
pushed second.
> + return;
> + }
> +
> + cur = str;
> + out = escaped;
> +
> + /* Add outer '...' only if arg included shell metacharacters. */
> + if (strpbrk(str, "\r\t\n !\"#$&'()*;<>?[\\]^`{|}~")) {
Hmm, I'm wondering if we should include '=' in this list, possibly
conditionally? That is, in shell, 'a=b' is much different from a=b (the
former runs the command literally named "a=b", the latter affects the
shell variable named "a"). At the same time, I want to someday make
virCommand use this method to output env-var settings, in a nicely
quoted manner (that is, as "a='b c'" rather than "'a=b c'"). But I'll
worry about that later; for now, this matches the string in tools/virsh.c.
> + *out++ = '\'';
> + close_quote = true;
> + }
Here, you have already proven there is nothing to quote; you could just
call virBufferAdd and return early here. Then you wouldn't even have to
track close_quote - if you get past the short-circuit, then it is
obvious that quoting is needed.
Do we need to worry about the special case of the empty string? That
is, if len == 0, should we append '' to the buffer rather than being a
no-op?
> + while (*cur != 0) {
> + if (*cur == '\'') {
> + /* Replace literal ' with a close ', a \', and a open ' */
> + *out++ = '\'';
> + *out++ = '\\';
> + *out++ = *cur++;
> + *out++ = '\'';
> + } else
> + *out++ = *cur++;
Style. If one branch of if-else needs braces, then both should have it:
if {
...
} else {
*out++ = *cur++;
}
Since it has been so long since this was first reported; I'm tempted to
conditionally ACK this and leave it up to you if you post a v3 or just
push things with my nits fixed.
--
Eric Blake eblake at redhat.com +1-801-349-2682
Libvirt virtualization library http://libvirt.org
More information about the libvir-list
mailing list