
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@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org