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

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



On Wed, Oct 12, 2011 at 05:16:35PM -0600, Eric Blake wrote:
> 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?

Yes, it's more like cmdEcho now ;)

> 
> >---
> >  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).

Done.

> 
> >+++ 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)

Done.

> 
> >+
> >+    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.

Done.

> 
> 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++;

Since we're copying the same char in if and else I dropped else
entirely.

> 
> 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.
New version attached.
Cheers,
 -- Guido
>From 452456fa556af40ac6de1cc8c91dd4bafca15d1b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Guido=20G=C3=BCnther?= <agx sigxcpu org>
Date: Thu, 28 Jul 2011 15:25:00 +0200
Subject: [PATCH 2/4] Add virBufferEscapeShell

Escape strings so they're safe to pass to the shell. It's based on
virsh's 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..0c26ba7 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -28,6 +28,7 @@ virBufferError;
 virBufferEscape;
 virBufferEscapeSexpr;
 virBufferEscapeString;
+virBufferEscapeShell;
 virBufferFreeAndReset;
 virBufferStrcat;
 virBufferURIEncodeString;
diff --git a/src/util/buf.c b/src/util/buf.c
index fa12855..34347b5 100644
--- a/src/util/buf.c
+++ 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 to mean str.
+ */
+void
+virBufferEscapeShell(virBufferPtr buf, const char *str)
+{
+    int len;
+    char *escaped, *out;
+    const char *cur;
+
+    if ((buf == NULL) || (str == NULL))
+        return;
+
+    if (buf->error)
+        return;
+
+    /* Only quote if str includes shell metacharacters. */
+    if (!strpbrk(str, "\r\t\n !\"#$&'()*;<>?[\\]^`{|}~")) {
+        virBufferAdd(buf, str, -1);
+        return;
+    }
+
+    len = strlen(str);
+    if (xalloc_oversized(4, len) ||
+        VIR_ALLOC_N(escaped, 4 * len + 3) < 0) {
+        virBufferSetError(buf);
+        return;
+    }
+
+    cur = str;
+    out = escaped;
+
+    *out++ = '\'';
+    while (*cur != 0) {
+        *out++ = *cur++;
+        if (*cur == '\'') {
+            /* Replace literal ' with a close ', a \', and a open ' */
+            *out++ = '\\';
+            *out++ = '\'';
+            *out++ = '\'';
+        }
+    }
+    *out++ = '\'';
+    *out = 0;
+
+    virBufferAdd(buf, escaped, -1);
+    VIR_FREE(escaped);
+}
+
+/**
  * virBufferStrcat:
  * @buf:  the buffer to dump
  * @...:  the variable list of strings, the last argument must be NULL
diff --git a/src/util/buf.h b/src/util/buf.h
index e545ed9..1d0e790 100644
--- a/src/util/buf.h
+++ b/src/util/buf.h
@@ -52,6 +52,7 @@ void virBufferEscapeString(const virBufferPtr buf, const char *format, const cha
 void virBufferEscapeSexpr(const virBufferPtr buf, const char *format, const char *str);
 void virBufferEscape(const virBufferPtr buf, const char *toescape, const char *format, const char *str);
 void virBufferURIEncodeString (const virBufferPtr buf, const char *str);
+void virBufferEscapeShell(virBufferPtr buf, const char *str);
 
 # define virBufferAddLit(buf_, literal_string_) \
   virBufferAdd (buf_, "" literal_string_ "", sizeof literal_string_ - 1)
-- 
1.7.6.3


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