Add a helper to escape all possible meta-characters used for
POSIX extended regular expressions.
Signed-off-by: Pavel Hrdina <phrdina(a)redhat.com>
---
new in v2
src/libvirt_private.syms | 1 +
src/util/virbuffer.c | 19 +++++++++++++++++++
src/util/virbuffer.h | 3 +++
tests/virbuftest.c | 40 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 63 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d32c6e7549..bbe283529b 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1312,6 +1312,7 @@ virBufferCurrentContent;
virBufferError;
virBufferEscape;
virBufferEscapeN;
+virBufferEscapeRegex;
virBufferEscapeSexpr;
virBufferEscapeShell;
virBufferEscapeString;
diff --git a/src/util/virbuffer.c b/src/util/virbuffer.c
index 80c8e289d4..f07b119c0f 100644
--- a/src/util/virbuffer.c
+++ b/src/util/virbuffer.c
@@ -556,6 +556,25 @@ virBufferEscapeSexpr(virBufferPtr buf,
}
/**
+ * virBufferEscapeRegex:
+ * @buf: the buffer to append to
+ * @format: a printf like format string but with only one %s parameter
+ * @str: the string argument which needs to be escaped
+ *
+ * Do a formatted print with a single string to a buffer. The @str is
+ * escaped to avoid using POSIX extended regular expression meta-characters.
+ * Escaping is not applied to characters specified in @format. Auto
+ * indentation may be applied.
+ */
+void
+virBufferEscapeRegex(virBufferPtr buf,
+ const char *format,
+ const char *str)
+{
+ virBufferEscape(buf, '\\', "^$.|?*+()[]{}\\", format, str);
+}
+
+/**
* virBufferEscape:
* @buf: the buffer to append to
* @escape: the escape character to inject
diff --git a/src/util/virbuffer.h b/src/util/virbuffer.h
index d1b64ca3a3..7a7014aa70 100644
--- a/src/util/virbuffer.h
+++ b/src/util/virbuffer.h
@@ -88,6 +88,9 @@ void virBufferEscapeString(virBufferPtr buf, const char *format,
const char *str);
void virBufferEscapeSexpr(virBufferPtr buf, const char *format,
const char *str);
+void virBufferEscapeRegex(virBufferPtr buf,
+ const char *format,
+ const char *str);
void virBufferEscapeShell(virBufferPtr buf, const char *str);
void virBufferURIEncodeString(virBufferPtr buf, const char *str);
diff --git a/tests/virbuftest.c b/tests/virbuftest.c
index 5905fee7d4..940e4c1c61 100644
--- a/tests/virbuftest.c
+++ b/tests/virbuftest.c
@@ -405,6 +405,35 @@ testBufEscapeN(const void *opaque)
static int
+testBufEscapeRegex(const void *opaque)
+{
+ const struct testBufAddStrData *data = opaque;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ char *actual;
+ int ret = -1;
+
+ virBufferEscapeRegex(&buf, "%s", data->data);
+
+ if (!(actual = virBufferContentAndReset(&buf))) {
+ VIR_TEST_DEBUG("testBufEscapeN: buf is empty");
+ goto cleanup;
+ }
+
+ if (STRNEQ_NULLABLE(actual, data->expect)) {
+ VIR_TEST_DEBUG("testBufEscapeN: Strings don't match:\n");
+ virTestDifference(stderr, data->expect, actual);
+ goto cleanup;
+ }
+
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(actual);
+ return ret;
+}
+
+
+static int
testBufSetIndent(const void *opaque ATTRIBUTE_UNUSED)
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
@@ -492,6 +521,17 @@ mymain(void)
DO_TEST_ESCAPEN("equal=escape", "equal\\=escape");
DO_TEST_ESCAPEN("comma,equal=escape", "comma,,equal\\=escape");
+#define DO_TEST_ESCAPE_REGEX(data, expect) \
+ do { \
+ struct testBufAddStrData info = { data, expect }; \
+ if (virTestRun("Buf: EscapeRegex", testBufEscapeRegex, &info) <
0) \
+ ret = -1; \
+ } while (0)
+
+ DO_TEST_ESCAPE_REGEX("noescape", "noescape");
+ DO_TEST_ESCAPE_REGEX("^$.|?*+()[]{}\\",
+ "\\^\\$\\.\\|\\?\\*\\+\\(\\)\\[\\]\\{\\}\\\\");
+
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
--
2.13.0