Strip control codes in virBufferEscapeString

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
This commit is contained in:
Ján Tomko 2015-03-30 12:41:40 +02:00
parent 60db2bc80f
commit aeb5262e43
2 changed files with 60 additions and 3 deletions

View File

@ -438,6 +438,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;
@ -446,7 +453,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;
}
@ -490,8 +497,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
@ -499,6 +505,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++;
}

View File

@ -348,6 +348,39 @@ testBufAddStr(const void *opaque ATTRIBUTE_UNUSED)
}
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)
{
@ -379,6 +412,22 @@ mymain(void)
DO_TEST_ADD_STR("<a/>\n", "<c>\n <a/>\n</c>");
DO_TEST_ADD_STR("<b>\n <a/>\n</b>\n", "<c>\n <b>\n <a/>\n </b>\n</c>");
#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;
}