]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Strip control codes in virBufferEscapeString
authorJán Tomko <jtomko@redhat.com>
Mon, 30 Mar 2015 10:41:40 +0000 (12:41 +0200)
committerJán Tomko <jtomko@redhat.com>
Wed, 15 Apr 2015 17:43:24 +0000 (19:43 +0200)
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
(cherry picked from commit aeb5262e4397528d582682471cb8075141189465)
Signed-off-by: Ján Tomko <jtomko@redhat.com>
Conflict:
  missing struct testBufAddStrData

src/util/virbuffer.c
tests/virbuftest.c

index 52ffa0814793c87506b1a064d120de79000f5162..3f6748c46511d70ce3a7386236cbe5e9153dc40c 100644 (file)
@@ -399,6 +399,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;
@@ -407,7 +414,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;
     }
@@ -451,8 +458,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
@@ -460,6 +466,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++;
     }
index 239889024657aedb814376cdaa378e9975b07300..af598d0e8020235f82d40c442e7ac8fe66a9bb07 100644 (file)
@@ -201,6 +201,45 @@ static int testBufTrim(const void *data ATTRIBUTE_UNUSED)
 }
 
 
+struct testBufAddStrData {
+    const char *data;
+    const char *expect;
+};
+
+
+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)
 {
@@ -219,6 +258,22 @@ mymain(void)
     DO_TEST("Auto-indentation", testBufAutoIndent, 0);
     DO_TEST("Trim", testBufTrim, 0);
 
+#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>&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;</el>\n</c>");
+    DO_TEST_ESCAPE("\007\"&&\"\x15",
+                   "<c>\n  <el>&quot;&amp;&amp;&quot;</el>\n</c>");
+    DO_TEST_ESCAPE(",,'..',,",
+                   "<c>\n  <el>,,&apos;..&apos;,,</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;
 }