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

Re: [libvirt] [PATCH 2/3] Add virBufferEscapeShell



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


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