diff --git a/src/util/virbuffer.c b/src/util/virbuffer.c index 52ffa08147..3f6748c465 100644 --- a/src/util/virbuffer.c +++ b/src/util/virbuffer.c @@ -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++; } diff --git a/tests/virbuftest.c b/tests/virbuftest.c index 2398890246..af598d0e80 100644 --- a/tests/virbuftest.c +++ b/tests/virbuftest.c @@ -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, "\n"); + virBufferAdjustIndent(&buf, 2); + virBufferEscapeString(&buf, "%s\n", data->data); + virBufferAdjustIndent(&buf, -2); + virBufferAddLit(&buf, ""); + + 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("", + "\n <td></td><td></td>\n"); + DO_TEST_ESCAPE("\007\"&&\"\x15", + "\n "&&"\n"); + DO_TEST_ESCAPE(",,'..',,", + "\n ,,'..',,\n"); + DO_TEST_ESCAPE("\x01\x01\x02\x03\x05\x08", + "\n \n"); + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; }