[Lldb-commits] [PATCH] Fix for PR25300

Tim Northover via lldb-commits lldb-commits at lists.llvm.org
Fri Oct 23 13:22:24 PDT 2015


Hi,

I decided to take a quick look at PR25300 (roughly, an '*' at the end
of an environment variable crashes lldb-server). The issue is that
during packet decompression (apparently even for uncompressed packets)
there is basic RLE, triggered by '*', so it needs to be quoted in some
way before being sent.

I came up with patches doing it in two different places (both attached here):

1. Switch to QEnvironmentHexEncoded if the string has these chars.
2. Safely escape these chars in SendPackedNoLock.

The second seems more robust and semantically correct (viewing only
'$' and '#' as characters that are actually special in a non
transport-dependent way). But it does have a performance overhead for
each packet sent (a likely not very optimised extra strcpy).

Which would be preferred, and does anyone have any hints on writing a
test for it? I can't see any existing QEnvironment tests to base mine
on.

Cheers.

Tim.
-------------- next part --------------
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index ea95298..9392af7 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -238,12 +238,29 @@ GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_le
 {
     if (IsConnected())
     {
-        StreamString packet(0, 4, eByteOrderBig);
+        std::string safe_payload;
+        safe_payload.reserve(payload_length);
+        for (const char *c = payload; c != payload + payload_length; ++c)
+        {
+            if (*c == '*' || *c == '}')
+            {
+                // These have special meaning even for nominally uncompressed
+                // strings, so we must escape them. Fortunately, the special
+                // meaning of '}' is precisely an escape of the next char (^
+                // 0x20).
+                safe_payload.push_back('}');
+                safe_payload.push_back(*c ^ 0x20);
+            }
+            else
+                safe_payload.push_back(*c);
+        }
+        payload_length = safe_payload.size();
 
+        StreamString packet(0, 4, eByteOrderBig);
         packet.PutChar('$');
-        packet.Write (payload, payload_length);
+        packet.Write (safe_payload.data(), payload_length);
         packet.PutChar('#');
-        packet.PutHex8(CalculcateChecksum (payload, payload_length));
+        packet.PutHex8(CalculcateChecksum (safe_payload.data(), payload_length));
 
         Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
         ConnectionStatus status = eConnectionStatusSuccess;
-------------- next part --------------
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index a6fcd14..5e0964b 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -1577,6 +1577,8 @@ GDBRemoteCommunicationClient::SendEnvironmentPacket (char const *name_equal_valu
                 {
                     case '$':
                     case '#':
+                    case '*':
+                    case '}':
                         send_hex_encoding = true;
                         break;
                     default:


More information about the lldb-commits mailing list