c5b0b3
From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
c5b0b3
Date: Tue, 14 Apr 2015 12:30:16 +0200
c5b0b3
Subject: [PATCH] Add functions dealing with control characters in strings
c5b0b3
c5b0b3
Add virStringHasControlChars that checks if the string has
c5b0b3
any control characters other than \t\r\n,
c5b0b3
and virStringStripControlChars that removes them in-place.
c5b0b3
c5b0b3
(cherry picked from commit 2a530a3e50d9314950cff0a5790c81910b0750a9)
c5b0b3
---
c5b0b3
 src/libvirt_private.syms |  2 ++
c5b0b3
 src/util/virstring.c     | 42 ++++++++++++++++++++++++++++++++++++++++++
c5b0b3
 src/util/virstring.h     |  2 ++
c5b0b3
 tests/virstringtest.c    | 39 +++++++++++++++++++++++++++++++++++++++
c5b0b3
 4 files changed, 85 insertions(+)
c5b0b3
c5b0b3
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
c5b0b3
index 5716ece..21b6aa5 100644
c5b0b3
--- a/src/libvirt_private.syms
c5b0b3
+++ b/src/libvirt_private.syms
c5b0b3
@@ -2121,6 +2121,7 @@ virStrdup;
c5b0b3
 virStringArrayHasString;
c5b0b3
 virStringFreeList;
c5b0b3
 virStringFreeListCount;
c5b0b3
+virStringHasControlChars;
c5b0b3
 virStringIsEmpty;
c5b0b3
 virStringJoin;
c5b0b3
 virStringListLength;
c5b0b3
@@ -2130,6 +2131,7 @@ virStringSortCompare;
c5b0b3
 virStringSortRevCompare;
c5b0b3
 virStringSplit;
c5b0b3
 virStringSplitCount;
c5b0b3
+virStringStripControlChars;
c5b0b3
 virStringStripIPv6Brackets;
c5b0b3
 virStrncpy;
c5b0b3
 virStrndup;
c5b0b3
diff --git a/src/util/virstring.c b/src/util/virstring.c
c5b0b3
index 3dad9dd..1cd4987 100644
c5b0b3
--- a/src/util/virstring.c
c5b0b3
+++ b/src/util/virstring.c
c5b0b3
@@ -968,3 +968,45 @@ virStringStripIPv6Brackets(char *str)
c5b0b3
         str[len - 2] = '\0';
c5b0b3
     }
c5b0b3
 }
c5b0b3
+
c5b0b3
+
c5b0b3
+static const char control_chars[] =
c5b0b3
+    "\x01\x02\x03\x04\x05\x06\x07"
c5b0b3
+    "\x08" /* \t \n */ "\x0B\x0C" /* \r */ "\x0E\x0F"
c5b0b3
+    "\x10\x11\x12\x13\x14\x15\x16\x17"
c5b0b3
+    "\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F";
c5b0b3
+
c5b0b3
+bool
c5b0b3
+virStringHasControlChars(const char *str)
c5b0b3
+{
c5b0b3
+    if (!str)
c5b0b3
+        return false;
c5b0b3
+
c5b0b3
+    return str[strcspn(str, control_chars)] != '\0';
c5b0b3
+}
c5b0b3
+
c5b0b3
+
c5b0b3
+/**
c5b0b3
+ * virStringStripControlChars:
c5b0b3
+ * @str: the string to strip
c5b0b3
+ *
c5b0b3
+ * Modify the string in-place to remove the control characters
c5b0b3
+ * in the interval: [0x01, 0x20)
c5b0b3
+ */
c5b0b3
+void
c5b0b3
+virStringStripControlChars(char *str)
c5b0b3
+{
c5b0b3
+    size_t len, i, j;
c5b0b3
+
c5b0b3
+    if (!str)
c5b0b3
+        return;
c5b0b3
+
c5b0b3
+    len = strlen(str);
c5b0b3
+    for (i = 0, j = 0; i < len; i++) {
c5b0b3
+        if (index(control_chars, str[i]))
c5b0b3
+            continue;
c5b0b3
+
c5b0b3
+        str[j++] = str[i];
c5b0b3
+    }
c5b0b3
+    str[j] = '\0';
c5b0b3
+}
c5b0b3
diff --git a/src/util/virstring.h b/src/util/virstring.h
c5b0b3
index 2ec60fa..e6dcb32 100644
c5b0b3
--- a/src/util/virstring.h
c5b0b3
+++ b/src/util/virstring.h
c5b0b3
@@ -271,5 +271,7 @@ char *virStringReplace(const char *haystack,
c5b0b3
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
c5b0b3
 
c5b0b3
 void virStringStripIPv6Brackets(char *str);
c5b0b3
+bool virStringHasControlChars(const char *str);
c5b0b3
+void virStringStripControlChars(char *str);
c5b0b3
 
c5b0b3
 #endif /* __VIR_STRING_H__ */
c5b0b3
diff --git a/tests/virstringtest.c b/tests/virstringtest.c
c5b0b3
index 9d0b438..38d0126 100644
c5b0b3
--- a/tests/virstringtest.c
c5b0b3
+++ b/tests/virstringtest.c
c5b0b3
@@ -551,6 +551,29 @@ static int testStripIPv6Brackets(const void *args)
c5b0b3
     return ret;
c5b0b3
 }
c5b0b3
 
c5b0b3
+static int testStripControlChars(const void *args)
c5b0b3
+{
c5b0b3
+    const struct testStripData *data = args;
c5b0b3
+    int ret = -1;
c5b0b3
+    char *res = NULL;
c5b0b3
+
c5b0b3
+    if (VIR_STRDUP(res, data->string) < 0)
c5b0b3
+        goto cleanup;
c5b0b3
+
c5b0b3
+    virStringStripControlChars(res);
c5b0b3
+
c5b0b3
+    if (STRNEQ_NULLABLE(res, data->result)) {
c5b0b3
+        fprintf(stderr, "Returned '%s', expected '%s'\n",
c5b0b3
+                NULLSTR(res), NULLSTR(data->result));
c5b0b3
+        goto cleanup;
c5b0b3
+    }
c5b0b3
+
c5b0b3
+    ret = 0;
c5b0b3
+
c5b0b3
+ cleanup:
c5b0b3
+    VIR_FREE(res);
c5b0b3
+    return ret;
c5b0b3
+}
c5b0b3
 
c5b0b3
 static int
c5b0b3
 mymain(void)
c5b0b3
@@ -783,6 +806,22 @@ mymain(void)
c5b0b3
     TEST_STRIP_IPV6_BRACKETS(":hello]", ":hello]");
c5b0b3
     TEST_STRIP_IPV6_BRACKETS(":[]:", ":[]:");
c5b0b3
 
c5b0b3
+#define TEST_STRIP_CONTROL_CHARS(str, res)                              \
c5b0b3
+    do {                                                                \
c5b0b3
+        struct testStripData stripData = {                              \
c5b0b3
+            .string = str,                                              \
c5b0b3
+            .result = res,                                              \
c5b0b3
+        };                                                              \
c5b0b3
+        if (virtTestRun("Strip control chars from " #str,               \
c5b0b3
+                        testStripControlChars, &stripData) < 0)         \
c5b0b3
+            ret = -1;                                                   \
c5b0b3
+    } while (0)
c5b0b3
+
c5b0b3
+    TEST_STRIP_CONTROL_CHARS(NULL, NULL);
c5b0b3
+    TEST_STRIP_CONTROL_CHARS("\nhello \r hello\t", "\nhello \r hello\t");
c5b0b3
+    TEST_STRIP_CONTROL_CHARS("\x01H\x02" "E\x03L\x04L\x05O", "HELLO");
c5b0b3
+    TEST_STRIP_CONTROL_CHARS("\x01\x02\x03\x04HELL\x05O", "HELLO");
c5b0b3
+    TEST_STRIP_CONTROL_CHARS("\nhello \x01\x07hello\t", "\nhello hello\t");
c5b0b3
     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
c5b0b3
 }
c5b0b3