[PATCH v5 3/6] winedbg: Escape XML special characters in qXfer reply.
Jinoh Kang
jinoh.kang.kr at gmail.com
Sat Nov 20 15:12:22 CST 2021
Loaded image paths that contain XML special characters may break GDB's
XML parser.
Fix this by escaping all dynamic strings that go into the XML replies.
Signed-off-by: Jinoh Kang <jinoh.kang.kr at gmail.com>
---
Notes:
strcspn() uses lookup tables as well, but as of Wine 6.22
msvcrt!strcspn allocates 1024 bytes (sizeof(BOOL)*256) of table
on the stack and populates it on the fly. It would be slower and
less cache-friendly than a preallocated, tiny static lookup table.
programs/winedbg/gdbproxy.c | 63 ++++++++++++++++++++++++++++++++-----
1 file changed, 56 insertions(+), 7 deletions(-)
diff --git a/programs/winedbg/gdbproxy.c b/programs/winedbg/gdbproxy.c
index a82588fd8b8..2534e2525b0 100644
--- a/programs/winedbg/gdbproxy.c
+++ b/programs/winedbg/gdbproxy.c
@@ -279,6 +279,55 @@ static inline void reply_buffer_append_uinthex(struct reply_buffer* reply, ULONG
reply_buffer_append(reply, ptr, len * 2);
}
+static const unsigned char xml_special_chars_lookup_table[16] = {
+ /* The characters should be sorted by its value modulo table length. */
+
+ 0x00, /* NUL */
+ 0,
+ 0x22, /* ": 0010|0010 */
+ 0, 0, 0,
+ 0x26, /* &: 0010|0110 */
+ 0x27, /* ': 0010|0111 */
+ 0, 0, 0, 0,
+ 0x3C, /* <: 0011|1100 */
+ 0,
+ 0x3E, /* >: 0011|1110 */
+ 0
+};
+
+static inline BOOL is_nul_or_xml_special_char(unsigned char val)
+{
+ const size_t length = ARRAY_SIZE(xml_special_chars_lookup_table);
+ return xml_special_chars_lookup_table[val % length] == val;
+}
+
+static void reply_buffer_append_xmlstr(struct reply_buffer* reply, const char* str)
+{
+ const char *ptr = str, *curr;
+
+ for (;;)
+ {
+ curr = ptr;
+
+ while (!is_nul_or_xml_special_char((unsigned char)*ptr))
+ ptr++;
+
+ reply_buffer_append(reply, curr, ptr - curr);
+
+ switch (*ptr++)
+ {
+ case '"': reply_buffer_append_str(reply, """); break;
+ case '&': reply_buffer_append_str(reply, "&"); break;
+ case '\'': reply_buffer_append_str(reply, "'"); break;
+ case '<': reply_buffer_append_str(reply, "<"); break;
+ case '>': reply_buffer_append_str(reply, ">"); break;
+ case '\0':
+ default:
+ return;
+ }
+ }
+}
+
static unsigned char checksum(const void* data, int len)
{
unsigned cksum = 0;
@@ -1618,9 +1667,9 @@ static BOOL CALLBACK packet_query_libraries_cb(PCSTR mod_name, DWORD64 base, PVO
reply_buffer_append_str(reply, "<library name=\"");
if (strcmp(mod.LoadedImageName, "[vdso].so") == 0)
- reply_buffer_append_str(reply, "linux-vdso.so.1");
+ reply_buffer_append_xmlstr(reply, "linux-vdso.so.1");
else if (mod.LoadedImageName[0] == '/')
- reply_buffer_append_str(reply, mod.LoadedImageName);
+ reply_buffer_append_xmlstr(reply, mod.LoadedImageName);
else
{
UNICODE_STRING nt_name;
@@ -1635,10 +1684,10 @@ static BOOL CALLBACK packet_query_libraries_cb(PCSTR mod_name, DWORD64 base, PVO
if (IsWow64Process(gdbctx->process->handle, &is_wow64) &&
is_wow64 && (tmp = strstr(unix_path, "system32")))
memcpy(tmp, "syswow64", 8);
- reply_buffer_append_str(reply, unix_path);
+ reply_buffer_append_xmlstr(reply, unix_path);
}
else
- reply_buffer_append_str(reply, mod.LoadedImageName);
+ reply_buffer_append_xmlstr(reply, mod.LoadedImageName);
HeapFree(GetProcessHeap(), 0, unix_path);
RtlFreeUnicodeString(&nt_name);
@@ -1755,8 +1804,8 @@ static void packet_query_target_xml(struct gdb_context* gdbctx, struct backend_c
feature = cpu->gdb_register_map[i].feature;
reply_buffer_append_str(reply, "<feature name=\"");
- if (feature_prefix) reply_buffer_append_str(reply, feature_prefix);
- reply_buffer_append_str(reply, feature);
+ if (feature_prefix) reply_buffer_append_xmlstr(reply, feature_prefix);
+ reply_buffer_append_xmlstr(reply, feature);
reply_buffer_append_str(reply, "\">");
if (strcmp(feature_prefix, "org.gnu.gdb.i386.") == 0 &&
@@ -1823,7 +1872,7 @@ static void packet_query_target_xml(struct gdb_context* gdbctx, struct backend_c
if (cpu->gdb_register_map[i].type)
{
reply_buffer_append_str(reply, " type=\"");
- reply_buffer_append_str(reply, cpu->gdb_register_map[i].type);
+ reply_buffer_append_xmlstr(reply, cpu->gdb_register_map[i].type);
reply_buffer_append_str(reply, "\"");
}
--
2.31.1
More information about the wine-devel
mailing list