[Lldb-commits] [lldb] r346988 - Add a check whether or not a str is utf8 prior to emplacing

Nathan Lanza via lldb-commits lldb-commits at lists.llvm.org
Thu Nov 15 11:49:57 PST 2018


Author: lanza
Date: Thu Nov 15 11:49:57 2018
New Revision: 346988

URL: http://llvm.org/viewvc/llvm-project?rev=346988&view=rev
Log:
Add a check whether or not a str is utf8 prior to emplacing

Summary:
Highlighing junk data on VSCode can send a query for evaluate which
fails. In particular cases on Windows, this the error message can end
up as a c-string of [-35,-35,-35,-35,...]. Attempting to emplace this
as the error message causes an assert failure.

Prior to emplacing the error message, confirm that it is valid UTF8 to
eliminate errors such as mentione above.

Reviewers: xiaobai, clayborg

Reviewed By: clayborg

Differential Revision: https://reviews.llvm.org/D53008

Modified:
    lldb/trunk/tools/lldb-vscode/JSONUtils.cpp
    lldb/trunk/tools/lldb-vscode/JSONUtils.h
    lldb/trunk/tools/lldb-vscode/VSCode.cpp
    lldb/trunk/tools/lldb-vscode/lldb-vscode.cpp

Modified: lldb/trunk/tools/lldb-vscode/JSONUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-vscode/JSONUtils.cpp?rev=346988&r1=346987&r2=346988&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-vscode/JSONUtils.cpp (original)
+++ lldb/trunk/tools/lldb-vscode/JSONUtils.cpp Thu Nov 15 11:49:57 2018
@@ -23,6 +23,14 @@
 
 namespace lldb_vscode {
 
+void EmplaceSafeString(llvm::json::Object &obj, llvm::StringRef key,
+                       llvm::StringRef str) {
+  if (LLVM_LIKELY(llvm::json::isUTF8(str)))
+    obj.try_emplace(key, str.str());
+  else
+    obj.try_emplace(key, llvm::json::fixUTF8(str));
+}
+
 llvm::StringRef GetAsString(const llvm::json::Value &value) {
   if (auto s = value.getAsString())
     return *s;
@@ -124,11 +132,11 @@ std::vector<std::string> GetStrings(cons
 
 void SetValueForKey(lldb::SBValue &v, llvm::json::Object &object,
                     llvm::StringRef key) {
-  
+
   llvm::StringRef value = v.GetValue();
   llvm::StringRef summary = v.GetSummary();
   llvm::StringRef type_name = v.GetType().GetDisplayTypeName();
-  
+
   std::string result;
   llvm::raw_string_ostream strm(result);
   if (!value.empty()) {
@@ -144,7 +152,7 @@ void SetValueForKey(lldb::SBValue &v, ll
       strm << " @ " << llvm::format_hex(address, 0);
   }
   strm.flush();
-  object.try_emplace(key, result);
+  EmplaceSafeString(object, key, result);
 }
 
 void FillResponse(const llvm::json::Object &request,
@@ -153,7 +161,7 @@ void FillResponse(const llvm::json::Obje
   // to true by default.
   response.try_emplace("type", "response");
   response.try_emplace("seq", (int64_t)0);
-  response.try_emplace("command", GetString(request, "command"));
+  EmplaceSafeString(response, "command", GetString(request, "command"));
   const int64_t seq = GetSigned(request, "seq", 0);
   response.try_emplace("request_seq", seq);
   response.try_emplace("success", true);
@@ -223,7 +231,7 @@ llvm::json::Value CreateScope(const llvm
                               int64_t variablesReference,
                               int64_t namedVariables, bool expensive) {
   llvm::json::Object object;
-  object.try_emplace("name", name.str());
+  EmplaceSafeString(object, "name", name.str());
   object.try_emplace("variablesReference", variablesReference);
   object.try_emplace("expensive", expensive);
   object.try_emplace("namedVariables", namedVariables);
@@ -357,7 +365,7 @@ llvm::json::Object CreateEventObject(con
   llvm::json::Object event;
   event.try_emplace("seq", 0);
   event.try_emplace("type", "event");
-  event.try_emplace("event", event_name);
+  EmplaceSafeString(event, "event", event_name);
   return event;
 }
 
@@ -388,8 +396,8 @@ llvm::json::Object CreateEventObject(con
 llvm::json::Value
 CreateExceptionBreakpointFilter(const ExceptionBreakpoint &bp) {
   llvm::json::Object object;
-  object.try_emplace("filter", bp.filter);
-  object.try_emplace("label", bp.label);
+  EmplaceSafeString(object, "filter", bp.filter);
+  EmplaceSafeString(object, "label", bp.label);
   object.try_emplace("default", bp.default_value);
   return llvm::json::Value(std::move(object));
 }
@@ -467,11 +475,11 @@ llvm::json::Value CreateSource(lldb::SBL
   if (file.IsValid()) {
     const char *name = file.GetFilename();
     if (name)
-      object.try_emplace("name", name);
+      EmplaceSafeString(object, "name", name);
     char path[PATH_MAX] = "";
     file.GetPath(path, sizeof(path));
     if (path[0]) {
-      object.try_emplace("path", std::string(path));
+      EmplaceSafeString(object, "path", std::string(path));
     }
   }
   return llvm::json::Value(std::move(object));
@@ -517,7 +525,7 @@ llvm::json::Value CreateSource(lldb::SBF
   }
   const auto num_insts = insts.GetSize();
   if (low_pc != LLDB_INVALID_ADDRESS && num_insts > 0) {
-    object.try_emplace("name", frame.GetFunctionName());
+    EmplaceSafeString(object, "name", frame.GetFunctionName());
     SourceReference source;
     llvm::raw_string_ostream src_strm(source.content);
     std::string line;
@@ -540,8 +548,8 @@ llvm::json::Value CreateSource(lldb::SBF
       line.clear();
       llvm::raw_string_ostream line_strm(line);
       line_strm << llvm::formatv("{0:X+}: <{1}> {2} {3,12} {4}", inst_addr,
-                                 inst_offset, llvm::fmt_repeat(' ', spaces),
-                                 m, o);
+                                 inst_offset, llvm::fmt_repeat(' ', spaces), m,
+                                 o);
 
       // If there is a comment append it starting at column 60 or after one
       // space past the last char
@@ -626,7 +634,7 @@ llvm::json::Value CreateStackFrame(lldb:
   llvm::json::Object object;
   int64_t frame_id = MakeVSCodeFrameID(frame);
   object.try_emplace("id", frame_id);
-  object.try_emplace("name", frame.GetFunctionName());
+  EmplaceSafeString(object, "name", frame.GetFunctionName());
   int64_t disasm_line = 0;
   object.try_emplace("source", CreateSource(frame, disasm_line));
 
@@ -670,9 +678,9 @@ llvm::json::Value CreateThread(lldb::SBT
     std::string thread_with_name(thread_str);
     thread_with_name += ' ';
     thread_with_name += name;
-    object.try_emplace("name", thread_with_name);
+    EmplaceSafeString(object, "name", thread_with_name);
   } else {
-    object.try_emplace("name", std::string(thread_str));
+    EmplaceSafeString(object, "name", std::string(thread_str));
   }
   return llvm::json::Value(std::move(object));
 }
@@ -749,7 +757,7 @@ llvm::json::Value CreateThreadStopped(ll
     ExceptionBreakpoint *exc_bp = g_vsc.GetExceptionBPFromStopReason(thread);
     if (exc_bp) {
       body.try_emplace("reason", "exception");
-      body.try_emplace("description", exc_bp->label);
+      EmplaceSafeString(body, "description", exc_bp->label);
     } else {
       body.try_emplace("reason", "breakpoint");
     }
@@ -782,7 +790,7 @@ llvm::json::Value CreateThreadStopped(ll
   if (ObjectContainsKey(body, "description")) {
     char description[1024];
     if (thread.GetStopDescription(description, sizeof(description))) {
-      body.try_emplace("description", std::string(description));
+      EmplaceSafeString(body, "description", std::string(description));
     }
   }
   if (tid == g_vsc.focus_tid) {
@@ -862,12 +870,12 @@ llvm::json::Value CreateVariable(lldb::S
                                  int64_t varID, bool format_hex) {
   llvm::json::Object object;
   auto name = v.GetName();
-  object.try_emplace("name", name ? name : "<null>");
+  EmplaceSafeString(object, "name", name ? name : "<null>");
   if (format_hex)
     v.SetFormat(lldb::eFormatHex);
   SetValueForKey(v, object, "value");
   auto type_cstr = v.GetType().GetDisplayTypeName();
-  object.try_emplace("type", type_cstr ? type_cstr : NO_TYPENAME);
+  EmplaceSafeString(object, "type", type_cstr ? type_cstr : NO_TYPENAME);
   if (varID != INT64_MAX)
     object.try_emplace("id", varID);
   if (v.MightHaveChildren())
@@ -878,7 +886,7 @@ llvm::json::Value CreateVariable(lldb::S
   v.GetExpressionPath(evaluateStream);
   const char *evaluateName = evaluateStream.GetData();
   if (evaluateName && evaluateName[0])
-    object.try_emplace("evaluateName", std::string(evaluateName));
+    EmplaceSafeString(object, "evaluateName", std::string(evaluateName));
   return llvm::json::Value(std::move(object));
 }
 

Modified: lldb/trunk/tools/lldb-vscode/JSONUtils.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-vscode/JSONUtils.h?rev=346988&r1=346987&r2=346988&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-vscode/JSONUtils.h (original)
+++ lldb/trunk/tools/lldb-vscode/JSONUtils.h Thu Nov 15 11:49:57 2018
@@ -16,7 +16,24 @@
 #include "VSCodeForward.h"
 
 namespace lldb_vscode {
-  
+
+//------------------------------------------------------------------
+/// Emplace a StringRef in a json::Object after enusring that the
+/// string is valid UTF8. If not, first call llvm::json::fixUTF8
+/// before emplacing.
+///
+/// @param[in] obj
+///     A JSON object that we will attempt to emplace the value in
+///
+/// @param[in] key
+///     The key to use when emplacing the value
+///
+/// @param[in] str
+///     The string to emplace
+//------------------------------------------------------------------
+void EmplaceSafeString(llvm::json::Object &obj, llvm::StringRef key,
+                       llvm::StringRef str);
+
 //------------------------------------------------------------------
 /// Extract simple values as a string.
 ///

Modified: lldb/trunk/tools/lldb-vscode/VSCode.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-vscode/VSCode.cpp?rev=346988&r1=346987&r2=346988&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-vscode/VSCode.cpp (original)
+++ lldb/trunk/tools/lldb-vscode/VSCode.cpp Thu Nov 15 11:49:57 2018
@@ -256,7 +256,7 @@ void VSCode::SendOutput(OutputType o, co
     break;
   }
   body.try_emplace("category", category);
-  body.try_emplace("output", output.str());
+  EmplaceSafeString(body, "output", output.str());
   event.try_emplace("body", std::move(body));
   SendJSON(llvm::json::Value(std::move(event)));
 }

Modified: lldb/trunk/tools/lldb-vscode/lldb-vscode.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-vscode/lldb-vscode.cpp?rev=346988&r1=346987&r2=346988&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-vscode/lldb-vscode.cpp (original)
+++ lldb/trunk/tools/lldb-vscode/lldb-vscode.cpp Thu Nov 15 11:49:57 2018
@@ -289,7 +289,7 @@ void SendProcessEvent(LaunchMethod launc
   exe_fspec.GetPath(exe_path, sizeof(exe_path));
   llvm::json::Object event(CreateEventObject("process"));
   llvm::json::Object body;
-  body.try_emplace("name", std::string(exe_path));
+  EmplaceSafeString(body, "name", std::string(exe_path));
   const auto pid = g_vsc.target.GetProcess().GetProcessID();
   body.try_emplace("systemProcessId", (int64_t)pid);
   body.try_emplace("isLocalProcess", true);
@@ -539,7 +539,7 @@ void request_attach(const llvm::json::Ob
     g_vsc.target.AddModule(program.data(), target_triple, uuid_cstr, symfile);
     if (error.Fail()) {
       response.try_emplace("success", false);
-      response.try_emplace("message", std::string(error.GetCString()));
+      EmplaceSafeString(response, "message", std::string(error.GetCString()));
       g_vsc.SendJSON(llvm::json::Value(std::move(response)));
       return;
     }
@@ -591,7 +591,7 @@ void request_attach(const llvm::json::Ob
 
   if (error.Fail()) {
     response.try_emplace("success", false);
-    response.try_emplace("message", std::string(error.GetCString()));
+    EmplaceSafeString(response, "message", std::string(error.GetCString()));
   }
   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
   if (error.Success()) {
@@ -813,8 +813,8 @@ void request_exceptionInfo(const llvm::j
     else if (stopReason == lldb::eStopReasonBreakpoint) {
       ExceptionBreakpoint *exc_bp = g_vsc.GetExceptionBPFromStopReason(thread);
       if (exc_bp) {
-        body.try_emplace("exceptionId", exc_bp->filter);
-        body.try_emplace("description", exc_bp->label);
+        EmplaceSafeString(body, "exceptionId", exc_bp->filter);
+        EmplaceSafeString(body, "description", exc_bp->label);
       } else {
         body.try_emplace("exceptionId", "exception");
       }
@@ -824,7 +824,7 @@ void request_exceptionInfo(const llvm::j
     if (!ObjectContainsKey(body, "description")) {
       char description[1024];
       if (thread.GetStopDescription(description, sizeof(description))) {
-        body.try_emplace("description", std::string(description));
+        EmplaceSafeString(body, "description", std::string(description));
       }
     }
     body.try_emplace("breakMode", "always");
@@ -951,9 +951,9 @@ void request_evaluate(const llvm::json::
   const auto expression = GetString(arguments, "expression");
 
   if (!expression.empty() && expression[0] == '`') {
-    body.try_emplace("result",
-                     RunLLDBCommands(llvm::StringRef(),
-                                     {expression.substr(1)}));
+    auto result = RunLLDBCommands(llvm::StringRef(),
+                                     {expression.substr(1)});
+    EmplaceSafeString(body, "result", result);
     body.try_emplace("variablesReference", (int64_t)0);
   } else {
     // Always try to get the answer from the local variables if possible. If
@@ -968,13 +968,13 @@ void request_evaluate(const llvm::json::
       response.try_emplace("success", false);
       const char *error_cstr = value.GetError().GetCString();
       if (error_cstr && error_cstr[0])
-        response.try_emplace("message", std::string(error_cstr));
+        EmplaceSafeString(response, "message", std::string(error_cstr));
       else
-        response.try_emplace("message", "evaluate failed");
+        EmplaceSafeString(response, "message", "evaluate failed");
     } else {
       SetValueForKey(value, body, "result");
       auto value_typename = value.GetType().GetDisplayTypeName();
-      body.try_emplace("type", value_typename ? value_typename : NO_TYPENAME);
+      EmplaceSafeString(body, "type", value_typename ? value_typename : NO_TYPENAME);
       if (value.MightHaveChildren()) {
         auto variablesReference = VARIDX_TO_VARREF(g_vsc.variables.GetSize());
         g_vsc.variables.Append(value);
@@ -1241,7 +1241,7 @@ void request_launch(const llvm::json::Ob
     g_vsc.target.AddModule(program.data(), target_triple, uuid_cstr, symfile);
     if (error.Fail()) {
       response.try_emplace("success", false);
-      response.try_emplace("message", std::string(error.GetCString()));
+      EmplaceSafeString(response, "message", std::string(error.GetCString()));
       g_vsc.SendJSON(llvm::json::Value(std::move(response)));
     }
   }
@@ -1279,7 +1279,7 @@ void request_launch(const llvm::json::Ob
   g_vsc.target.Launch(g_vsc.launch_info, error);
   if (error.Fail()) {
     response.try_emplace("success", false);
-    response.try_emplace("message", std::string(error.GetCString()));
+    EmplaceSafeString(response, "message", std::string(error.GetCString()));
   }
   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
 
@@ -1945,7 +1945,7 @@ void request_source(const llvm::json::Ob
   auto sourceReference = GetSigned(source, "sourceReference", -1);
   auto pos = g_vsc.source_map.find((lldb::addr_t)sourceReference);
   if (pos != g_vsc.source_map.end()) {
-    body.try_emplace("content", pos->second.content);
+    EmplaceSafeString(body, "content", pos->second.content);
   } else {
     response.try_emplace("success", false);
   }
@@ -2406,10 +2406,10 @@ void request_setVariable(const llvm::jso
     bool success = variable.SetValueFromCString(value.data(), error);
     if (success) {
       SetValueForKey(variable, body, "value");
-      body.try_emplace("type", variable.GetType().GetDisplayTypeName());
+      EmplaceSafeString(body, "type", variable.GetType().GetDisplayTypeName());
       body.try_emplace("variablesReference", newVariablesReference);
     } else {
-      body.try_emplace("message", std::string(error.GetCString()));
+      EmplaceSafeString(body, "message", std::string(error.GetCString()));
     }
     response.try_emplace("success", success);
   }




More information about the lldb-commits mailing list