[libvirt] [PATCH] xml: shell-escape domain name in comment

Ján Tomko jtomko at redhat.com
Wed Oct 24 12:03:12 UTC 2012


Add virBufferEscapeShellXMLComment function that both quotes a string so
shell deosn't interpert any special characters in it and makes sure that
there's no "--" in it, to avoid clashes with XML comments.

virXMLEmitWarning is changed to use virBuffer and use the above function
on the domain name.
---
 src/libvirt_private.syms |    1 +
 src/util/buf.c           |   66 ++++++++++++++++++++++++++++++++++++++++++++++
 src/util/buf.h           |    1 +
 src/util/xml.c           |   52 +++++++++++++++---------------------
 4 files changed, 90 insertions(+), 30 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 699c9a3..a49d5dc 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -37,6 +37,7 @@ virBufferError;
 virBufferEscape;
 virBufferEscapeSexpr;
 virBufferEscapeShell;
+virBufferEscapeShellXML;
 virBufferEscapeString;
 virBufferFreeAndReset;
 virBufferGetIndent;
diff --git a/src/util/buf.c b/src/util/buf.c
index 030dc97..839b663 100644
--- a/src/util/buf.c
+++ b/src/util/buf.c
@@ -623,6 +623,72 @@ virBufferEscapeShell(virBufferPtr buf, const char *str)
 }
 
 /**
+ * virBufferEscapeShellXMLComment:
+ * @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.  Auto indentation may be applied.
+ * It also escapes any "--" so that the string can be used in XML comments.
+ */
+void virBufferEscapeShellXMLComment(virBufferPtr buf, const char *str)
+{
+    int len;
+    char *escaped, *out;
+    const char *cur;
+    char prev = '\0';
+
+    if ((buf == NULL) || (str == NULL))
+        return;
+
+    if (buf->error)
+        return;
+
+    /* Only quote if str includes shell metacharacters. */
+    if (*str && !strpbrk(str, "\r\t\n !\"#$&'()*;<>?[\\]^`{|}~") &&
+        !strstr(str,"--")) {
+        virBufferAdd(buf, str, -1);
+        return;
+    }
+
+    if (*str) {
+        len = strlen(str);
+        if (xalloc_oversized(4, len) ||
+            VIR_ALLOC_N(escaped, 4 * len + 3) < 0) {
+            virBufferSetError(buf, errno);
+            return;
+        }
+    } else {
+        virBufferAddLit(buf, "''");
+        return;
+    }
+
+    cur = str;
+    out = escaped;
+
+    *out++ = '\'';
+    while (*cur != 0) {
+        if (*cur == '\'') {
+            *out++ = '\'';
+            /* Replace literal ' with a close ', a \', and a open ' */
+            *out++ = '\\';
+            *out++ = '\'';
+        } else if (*cur == '-' &&  prev == '-') {
+            /* Replace -- with -''- */
+            *out++ = '\'';
+            *out++ = '\'';
+        }
+        prev = *cur;
+        *out++ = *cur++;
+    }
+    *out++ = '\'';
+    *out = 0;
+
+    virBufferAdd(buf, escaped, -1);
+    VIR_FREE(escaped);
+}
+
+/**
  * virBufferStrcat:
  * @buf: the buffer to append to
  * @...:  the variable list of strings, the last argument must be NULL
diff --git a/src/util/buf.h b/src/util/buf.h
index c3a498d..25e31fd 100644
--- a/src/util/buf.h
+++ b/src/util/buf.h
@@ -69,6 +69,7 @@ void virBufferEscapeString(virBufferPtr buf, const char *format,
 void virBufferEscapeSexpr(virBufferPtr buf, const char *format,
                           const char *str);
 void virBufferEscapeShell(virBufferPtr buf, const char *str);
+void virBufferEscapeShellXMLComment(virBufferPtr buf, const char *str);
 void virBufferURIEncodeString(virBufferPtr buf, const char *str);
 
 # define virBufferAddLit(buf_, literal_string_) \
diff --git a/src/util/xml.c b/src/util/xml.c
index f3dc256..685f903 100644
--- a/src/util/xml.c
+++ b/src/util/xml.c
@@ -780,49 +780,41 @@ error:
     goto cleanup;
 }
 
-
 static int virXMLEmitWarning(int fd,
                              const char *name,
                              const char *cmd)
 {
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    char *str = NULL;
     size_t len;
-    const char *prologue = "<!--\n\
-WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE \n\
-OVERWRITTEN AND LOST. Changes to this xml configuration should be made using:\n\
-  virsh ";
-    const char *epilogue = "\n\
-or other application using the libvirt API.\n\
--->\n\n";
 
     if (fd < 0 || !name || !cmd) {
         errno = EINVAL;
         return -1;
     }
 
-    len = strlen(prologue);
-    if (safewrite(fd, prologue, len) != len)
-        return -1;
-
-    len = strlen(cmd);
-    if (safewrite(fd, cmd, len) != len)
-        return -1;
-
-    /* Omit the domain name if it contains a double hyphen
-     * because they aren't allowed in XML comments */
-    if (!strstr(name, "--")) {
-        if (safewrite(fd, " ", 1) != 1)
-            return -1;
-
-        len = strlen(name);
-        if (safewrite(fd, name, len) != len)
-            return -1;
+    virBufferAddLit(&buf, "<!--\n"
+"WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE\n"
+"OVERWRITTEN AND LOST. Changes to this xml configuration should be made using:\n"
+"  virsh ");
+    virBufferAdd(&buf, cmd, -1);
+    virBufferAddLit(&buf," ");
+    virBufferEscapeShellXMLComment(&buf, name);
+    virBufferAddLit(&buf, "\n"
+"or other application using the libvirt API.\n"
+"-->\n\n");
+
+    str = virBufferContentAndReset(&buf);
+    if (str) {
+        len = strlen(str);
+        if (safewrite(fd, str, len) == len) {
+            VIR_FREE(str);
+            return 0;
+        }
     }
 
-    len = strlen(epilogue);
-    if (safewrite(fd, epilogue, len) != len)
-        return -1;
-
-    return 0;
+    VIR_FREE(str);
+    return -1;
 }
 
 
-- 
1.7.8.6




More information about the libvir-list mailing list