Jinoh Kang : winedbg: Escape XML special characters in qXfer reply.

Alexandre Julliard julliard at winehq.org
Tue Nov 23 16:03:31 CST 2021


Module: wine
Branch: master
Commit: 4c01e00dbdc370176b2c692e00ac7b75d72f8e7f
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=4c01e00dbdc370176b2c692e00ac7b75d72f8e7f

Author: Jinoh Kang <jinoh.kang.kr at gmail.com>
Date:   Wed Nov 24 00:10:49 2021 +0900

winedbg: Escape XML special characters in qXfer reply.

Some dynamic strings (e.g. loaded image paths) may contain XML special
characters which breaks parsing.

Fix this by escaping all dynamic strings (i.e. character data and
attribute values) that go into the XML replies.

Signed-off-by: Jinoh Kang <jinoh.kang.kr at gmail.com>
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 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 a1ecdea770f..3d6aa02824e 100644
--- a/programs/winedbg/gdbproxy.c
+++ b/programs/winedbg/gdbproxy.c
@@ -284,6 +284,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;
@@ -1621,9 +1670,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;
@@ -1638,10 +1687,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);
@@ -1758,8 +1807,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 &&
@@ -1826,7 +1875,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, "\"");
         }
 




More information about the wine-cvs mailing list