[libvirt] [PATCH] Strip control codes in virBufferEscapeString

Ján Tomko jtomko at redhat.com
Mon Mar 30 11:02:49 UTC 2015


These cannot be represented in XML.

We have been stripping them, but only if the string had
characters that needed escaping: <>"'&

Extend the strcspn check to include control codes, and strip
them even if we don't do any escaping.

https://bugzilla.redhat.com/show_bug.cgi?id=1184131
https://bugzilla.redhat.com/show_bug.cgi?id=1066564
---
 src/util/virbuffer.c | 14 +++++++++++---
 tests/virbuftest.c   | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+), 3 deletions(-)

diff --git a/src/util/virbuffer.c b/src/util/virbuffer.c
index 706dbfa..3d13c90 100644
--- a/src/util/virbuffer.c
+++ b/src/util/virbuffer.c
@@ -438,6 +438,13 @@ virBufferEscapeString(virBufferPtr buf, const char *format, const char *str)
     int len;
     char *escaped, *out;
     const char *cur;
+    const char forbidden_characters[] = {
+        0x01,   0x02,   0x03,   0x04,   0x05,   0x06,   0x07,   0x08,
+        /*\t*/  /*\n*/  0x0B,   0x0C,   /*\r*/  0x0E,   0x0F,   0x10,
+        0x11,   0x12,   0x13,   0x14,   0x15,   0x16,   0x17,   0x18,
+        0x19,   '"',    '&',    '\'',   '<',    '>',
+        '\0'
+    };
 
     if ((format == NULL) || (buf == NULL) || (str == NULL))
         return;
@@ -446,7 +453,7 @@ virBufferEscapeString(virBufferPtr buf, const char *format, const char *str)
         return;
 
     len = strlen(str);
-    if (strcspn(str, "<>&'\"") == len) {
+    if (strcspn(str, forbidden_characters) == len) {
         virBufferAsprintf(buf, format, str);
         return;
     }
@@ -490,8 +497,7 @@ virBufferEscapeString(virBufferPtr buf, const char *format, const char *str)
             *out++ = 'o';
             *out++ = 's';
             *out++ = ';';
-        } else if (((unsigned char)*cur >= 0x20) || (*cur == '\n') || (*cur == '\t') ||
-                   (*cur == '\r')) {
+        } else if (!strchr(forbidden_characters, *cur)) {
             /*
              * default case, just copy !
              * Note that character over 0x80 are likely to give problem
@@ -499,6 +505,8 @@ virBufferEscapeString(virBufferPtr buf, const char *format, const char *str)
              * it's hard to handle properly we have to assume it's UTF-8 too
              */
             *out++ = *cur;
+        } else {
+            /* silently ignore control characters */
         }
         cur++;
     }
diff --git a/tests/virbuftest.c b/tests/virbuftest.c
index 21cb18b..10398d5 100644
--- a/tests/virbuftest.c
+++ b/tests/virbuftest.c
@@ -349,6 +349,39 @@ testBufAddStr(const void *opaque ATTRIBUTE_UNUSED)
 
 
 static int
+testBufEscapeStr(const void *opaque ATTRIBUTE_UNUSED)
+{
+    const struct testBufAddStrData *data = opaque;
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    char *actual;
+    int ret = -1;
+
+    virBufferAddLit(&buf, "<c>\n");
+    virBufferAdjustIndent(&buf, 2);
+    virBufferEscapeString(&buf, "<el>%s</el>\n", data->data);
+    virBufferAdjustIndent(&buf, -2);
+    virBufferAddLit(&buf, "</c>");
+
+    if (!(actual = virBufferContentAndReset(&buf))) {
+        TEST_ERROR("buf is empty");
+        goto cleanup;
+    }
+
+    if (STRNEQ_NULLABLE(actual, data->expect)) {
+        TEST_ERROR("testBufEscapeStr(): Strings don't match:\n");
+        virtTestDifference(stderr, data->expect, actual);
+        goto cleanup;
+    }
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(actual);
+    return ret;
+}
+
+
+static int
 mymain(void)
 {
     int ret = 0;
@@ -379,6 +412,22 @@ mymain(void)
     DO_TEST_ADD_STR("<a/>\n", "<c>\n  <a/>\n</c>");
     DO_TEST_ADD_STR("<b>\n  <a/>\n</b>\n", "<c>\n  <b>\n    <a/>\n  </b>\n</c>");
 
+#define DO_TEST_ESCAPE(data, expect)                                   \
+    do {                                                               \
+        struct testBufAddStrData info = { data, expect };              \
+        if (virtTestRun("Buf: EscapeStr", testBufEscapeStr, &info) < 0)   \
+            ret = -1;                                                  \
+    } while (0)
+
+    DO_TEST_ESCAPE("<td></td><td></td>",
+                   "<c>\n  <el><td></td><td></td></el>\n</c>");
+    DO_TEST_ESCAPE("\007\"&&\"\x15",
+                   "<c>\n  <el>"&&"</el>\n</c>");
+    DO_TEST_ESCAPE(",,'..',,",
+                   "<c>\n  <el>,,'..',,</el>\n</c>");
+    DO_TEST_ESCAPE("\x01\x01\x02\x03\x05\x08",
+                   "<c>\n  <el></el>\n</c>");
+
     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
 
-- 
2.0.5




More information about the libvir-list mailing list