6d3351
From e302b6b9505730e9f1d139027c87867c973d2a26 Mon Sep 17 00:00:00 2001
6d3351
Message-Id: <e302b6b9505730e9f1d139027c87867c973d2a26@dist-git>
6d3351
From: Pavel Hrdina <phrdina@redhat.com>
6d3351
Date: Tue, 16 May 2017 11:46:12 +0200
6d3351
Subject: [PATCH] util: introduce virBufferEscapeRegex
6d3351
6d3351
Add a helper to escape all possible meta-characters used for
6d3351
POSIX extended regular expressions.
6d3351
6d3351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
6d3351
(cherry picked from commit 0918b84968ab8aeb1dc17d5da839d68d947f478f)
6d3351
6d3351
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1446980
6d3351
6d3351
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
6d3351
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
6d3351
---
6d3351
 src/libvirt_private.syms |  1 +
6d3351
 src/util/virbuffer.c     | 19 +++++++++++++++++++
6d3351
 src/util/virbuffer.h     |  3 +++
6d3351
 tests/virbuftest.c       | 40 ++++++++++++++++++++++++++++++++++++++++
6d3351
 4 files changed, 63 insertions(+)
6d3351
6d3351
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
6d3351
index 06c338384..7e1a06db3 100644
6d3351
--- a/src/libvirt_private.syms
6d3351
+++ b/src/libvirt_private.syms
6d3351
@@ -1292,6 +1292,7 @@ virBufferCurrentContent;
6d3351
 virBufferError;
6d3351
 virBufferEscape;
6d3351
 virBufferEscapeN;
6d3351
+virBufferEscapeRegex;
6d3351
 virBufferEscapeSexpr;
6d3351
 virBufferEscapeShell;
6d3351
 virBufferEscapeString;
6d3351
diff --git a/src/util/virbuffer.c b/src/util/virbuffer.c
6d3351
index 80c8e289d..f07b119c0 100644
6d3351
--- a/src/util/virbuffer.c
6d3351
+++ b/src/util/virbuffer.c
6d3351
@@ -556,6 +556,25 @@ virBufferEscapeSexpr(virBufferPtr buf,
6d3351
 }
6d3351
 
6d3351
 /**
6d3351
+ * virBufferEscapeRegex:
6d3351
+ * @buf: the buffer to append to
6d3351
+ * @format: a printf like format string but with only one %s parameter
6d3351
+ * @str: the string argument which needs to be escaped
6d3351
+ *
6d3351
+ * Do a formatted print with a single string to a buffer.  The @str is
6d3351
+ * escaped to avoid using POSIX extended regular expression meta-characters.
6d3351
+ * Escaping is not applied to characters specified in @format. Auto
6d3351
+ * indentation may be applied.
6d3351
+ */
6d3351
+void
6d3351
+virBufferEscapeRegex(virBufferPtr buf,
6d3351
+                     const char *format,
6d3351
+                     const char *str)
6d3351
+{
6d3351
+    virBufferEscape(buf, '\\', "^$.|?*+()[]{}\\", format, str);
6d3351
+}
6d3351
+
6d3351
+/**
6d3351
  * virBufferEscape:
6d3351
  * @buf: the buffer to append to
6d3351
  * @escape: the escape character to inject
6d3351
diff --git a/src/util/virbuffer.h b/src/util/virbuffer.h
6d3351
index d1b64ca3a..7a7014aa7 100644
6d3351
--- a/src/util/virbuffer.h
6d3351
+++ b/src/util/virbuffer.h
6d3351
@@ -88,6 +88,9 @@ void virBufferEscapeString(virBufferPtr buf, const char *format,
6d3351
                            const char *str);
6d3351
 void virBufferEscapeSexpr(virBufferPtr buf, const char *format,
6d3351
                           const char *str);
6d3351
+void virBufferEscapeRegex(virBufferPtr buf,
6d3351
+                          const char *format,
6d3351
+                          const char *str);
6d3351
 void virBufferEscapeShell(virBufferPtr buf, const char *str);
6d3351
 void virBufferURIEncodeString(virBufferPtr buf, const char *str);
6d3351
 
6d3351
diff --git a/tests/virbuftest.c b/tests/virbuftest.c
6d3351
index 8ec6ce51e..6f8d4b72c 100644
6d3351
--- a/tests/virbuftest.c
6d3351
+++ b/tests/virbuftest.c
6d3351
@@ -405,6 +405,35 @@ testBufEscapeN(const void *opaque)
6d3351
 
6d3351
 
6d3351
 static int
6d3351
+testBufEscapeRegex(const void *opaque)
6d3351
+{
6d3351
+    const struct testBufAddStrData *data = opaque;
6d3351
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
6d3351
+    char *actual;
6d3351
+    int ret = -1;
6d3351
+
6d3351
+    virBufferEscapeRegex(&buf, "%s", data->data);
6d3351
+
6d3351
+    if (!(actual = virBufferContentAndReset(&buf))) {
6d3351
+        VIR_TEST_DEBUG("testBufEscapeN: buf is empty");
6d3351
+        goto cleanup;
6d3351
+    }
6d3351
+
6d3351
+    if (STRNEQ_NULLABLE(actual, data->expect)) {
6d3351
+        VIR_TEST_DEBUG("testBufEscapeN: Strings don't match:\n");
6d3351
+        virTestDifference(stderr, data->expect, actual);
6d3351
+        goto cleanup;
6d3351
+    }
6d3351
+
6d3351
+    ret = 0;
6d3351
+
6d3351
+ cleanup:
6d3351
+    VIR_FREE(actual);
6d3351
+    return ret;
6d3351
+}
6d3351
+
6d3351
+
6d3351
+static int
6d3351
 testBufSetIndent(const void *opaque ATTRIBUTE_UNUSED)
6d3351
 {
6d3351
     virBuffer buf = VIR_BUFFER_INITIALIZER;
6d3351
@@ -492,6 +521,17 @@ mymain(void)
6d3351
     DO_TEST_ESCAPEN("equal=escape", "equal\\=escape");
6d3351
     DO_TEST_ESCAPEN("comma,equal=escape", "comma,,equal\\=escape");
6d3351
 
6d3351
+#define DO_TEST_ESCAPE_REGEX(data, expect)                                  \
6d3351
+    do {                                                                    \
6d3351
+        struct testBufAddStrData info = { data, expect };                   \
6d3351
+        if (virTestRun("Buf: EscapeRegex", testBufEscapeRegex, &info) < 0)  \
6d3351
+            ret = -1;                                                       \
6d3351
+    } while (0)
6d3351
+
6d3351
+    DO_TEST_ESCAPE_REGEX("noescape", "noescape");
6d3351
+    DO_TEST_ESCAPE_REGEX("^$.|?*+()[]{}\\",
6d3351
+                         "\\^\\$\\.\\|\\?\\*\\+\\(\\)\\[\\]\\{\\}\\\\");
6d3351
+
6d3351
     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
6d3351
 }
6d3351
 
6d3351
-- 
6d3351
2.13.0
6d3351