summaryrefslogtreecommitdiff
path: root/lldb/tools
diff options
context:
space:
mode:
authorNathan Lanza <nathan@lanza.io>2018-11-15 19:49:57 +0000
committerNathan Lanza <nathan@lanza.io>2018-11-15 19:49:57 +0000
commitc0ddff63820fd08c7173d707e00d6992352eea45 (patch)
treeec5681403997d51bc728effcaf5cfc60a01ebe23 /lldb/tools
parent94e67609f6a3bc47ced1ec4dff9e42fb834ffb12 (diff)
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
Diffstat (limited to 'lldb/tools')
-rw-r--r--lldb/tools/lldb-vscode/JSONUtils.cpp50
-rw-r--r--lldb/tools/lldb-vscode/JSONUtils.h19
-rw-r--r--lldb/tools/lldb-vscode/VSCode.cpp2
-rw-r--r--lldb/tools/lldb-vscode/lldb-vscode.cpp34
4 files changed, 65 insertions, 40 deletions
diff --git a/lldb/tools/lldb-vscode/JSONUtils.cpp b/lldb/tools/lldb-vscode/JSONUtils.cpp
index 019a9db624d..e80d9fca38f 100644
--- a/lldb/tools/lldb-vscode/JSONUtils.cpp
+++ b/lldb/tools/lldb-vscode/JSONUtils.cpp
@@ -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(const llvm::json::Object *obj,
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, llvm::json::Object &object,
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::Object &request,
// 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::StringRef name,
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(const llvm::StringRef event_name) {
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(const llvm::StringRef event_name) {
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::SBLineEntry &line_entry) {
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::SBFrame &frame, int64_t &disasm_line) {
}
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::SBFrame &frame, int64_t &disasm_line) {
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::SBFrame &frame) {
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::SBThread &thread) {
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(lldb::SBThread &thread,
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(lldb::SBThread &thread,
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::SBValue v, int64_t variablesReference,
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::SBValue v, int64_t variablesReference,
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));
}
diff --git a/lldb/tools/lldb-vscode/JSONUtils.h b/lldb/tools/lldb-vscode/JSONUtils.h
index 1ef3b733cfb..0ca000ce938 100644
--- a/lldb/tools/lldb-vscode/JSONUtils.h
+++ b/lldb/tools/lldb-vscode/JSONUtils.h
@@ -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.
///
diff --git a/lldb/tools/lldb-vscode/VSCode.cpp b/lldb/tools/lldb-vscode/VSCode.cpp
index d268c45aca6..0f138ec7770 100644
--- a/lldb/tools/lldb-vscode/VSCode.cpp
+++ b/lldb/tools/lldb-vscode/VSCode.cpp
@@ -256,7 +256,7 @@ void VSCode::SendOutput(OutputType o, const llvm::StringRef output) {
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)));
}
diff --git a/lldb/tools/lldb-vscode/lldb-vscode.cpp b/lldb/tools/lldb-vscode/lldb-vscode.cpp
index 8eacc541184..2aad7977efa 100644
--- a/lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ b/lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -289,7 +289,7 @@ void SendProcessEvent(LaunchMethod launch_method) {
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::Object &request) {
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::Object &request) {
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::json::Object &request) {
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::json::Object &request) {
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::Object &request) {
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::Object &request) {
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::Object &request) {
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::Object &request) {
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::Object &request) {
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::json::Object &request) {
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);
}