Fix crashes from badly formed json responses (LL's fault)

Adds LlsdFromJsonString, an exception-free wrapper for parsing json strings
LLSD objects that failed to parse through this will be the type Undefined.

Fixes crashes 36, 1G, 33, 21, and 3A.
This commit is contained in:
Liru Færs
2020-01-20 19:42:23 -05:00
parent 1fd6e91c68
commit deafc6814d
5 changed files with 61 additions and 14 deletions

View File

@@ -79,6 +79,17 @@ LLSD LlsdFromJson(const nlohmann::json &val)
return result;
}
LLSD LlsdFromJsonString(const std::string& str)
{
auto json = nlohmann::json::parse(str, nullptr, false);
if (json.is_discarded())
{
LL_WARNS() << "Cannot parse invalid json string:\n" << str << LL_ENDL;
return LLSD();
}
return LlsdFromJson(json);
}
//=========================================================================
nlohmann::json LlsdToJson(const LLSD &val)
{

View File

@@ -54,6 +54,7 @@
/// For maps and arrays child entries will be converted and added to the structure.
/// Order is preserved for an array but not for objects.
LLSD LlsdFromJson(const nlohmann::json &val);
LLSD LlsdFromJsonString(const std::string& body);
/// Convert an LLSD object into Parsed JSON object maintaining member names and
/// array indexs.

View File

@@ -281,8 +281,12 @@ public:
std::string body;
decode_raw_body(channels, buffer, body);
auto json = nlohmann::json::parse(body);
LLSD result = LlsdFromJson(json);;
LLSD result = LlsdFromJsonString(body);
if (result.isUndefined())
{
log_SLM_warning("Get /listings", getStatus(), getReason(), LLStringUtil::null, "Empty or Invalid JSON Response");
return;
}
if (!isGoodStatus(mStatus))
{
@@ -345,8 +349,12 @@ public:
std::string body;
decode_raw_body(channels, buffer, body);
auto json = nlohmann::json::parse(body);
LLSD result = LlsdFromJson(json);;
LLSD result = LlsdFromJsonString(body);
if (result.isUndefined())
{
log_SLM_warning("Post /listings", getStatus(), getReason(), LLStringUtil::null, "Empty or Invalid JSON Response");
return;
}
if (!isGoodStatus(mStatus))
{
@@ -404,8 +412,12 @@ public:
std::string body;
decode_raw_body(channels, buffer, body);
auto json = nlohmann::json::parse(body);
LLSD result = LlsdFromJson(json);
LLSD result = LlsdFromJsonString(body);
if (result.isUndefined())
{
log_SLM_warning("Get /listing", getStatus(), getReason(), LLStringUtil::null, "Empty or Invalid JSON Response");
return;
}
if (!isGoodStatus(mStatus))
{
@@ -480,8 +492,12 @@ public:
std::string body;
decode_raw_body(channels, buffer, body);
auto json = nlohmann::json::parse(body);
LLSD result = LlsdFromJson(json);
LLSD result = LlsdFromJsonString(body);
if (result.isUndefined())
{
log_SLM_warning("Put /listing", getStatus(), getReason(), LLStringUtil::null, "Empty or Invalid JSON Response");
return;
}
if (!isGoodStatus(mStatus))
{
@@ -557,8 +573,12 @@ public:
std::string body;
decode_raw_body(channels, buffer, body);
auto json = nlohmann::json::parse(body);
LLSD result = LlsdFromJson(json);
LLSD result = LlsdFromJsonString(body);
if (result.isUndefined())
{
log_SLM_warning("Put /associate_inventory", getStatus(), getReason(), LLStringUtil::null, "Empty or Invalid JSON Response");
return;
}
if (!isGoodStatus(mStatus))
{
@@ -629,8 +649,12 @@ public:
std::string body;
decode_raw_body(channels, buffer, body);
auto json = nlohmann::json::parse(body);
LLSD result = LlsdFromJson(json);
LLSD result = LlsdFromJsonString(body);
if (result.isUndefined())
{
log_SLM_warning("Delete /listing", getStatus(), getReason(), LLStringUtil::null, "Empty or Invalid JSON Response");
return;
}
if (!isGoodStatus(mStatus))
{

View File

@@ -82,7 +82,13 @@ public:
return;
}
auto root = LlsdFromJson(nlohmann::json::parse(body));
auto root = LlsdFromJsonString(body);
if (root.isUndefined())
{
LL_WARNS() << "Failed to get valid json body" << LL_ENDL;
LLWebProfile::reportImageUploadStatus(false);
return;
}
// *TODO: 404 = not supported by the grid
// *TODO: increase timeout or handle HTTP_INTERNAL_ERROR_* time errors.

View File

@@ -48,7 +48,12 @@ public:
return;
}
auto root = nlohmann::json::parse(body);
auto root = nlohmann::json::parse(body, nullptr, false);
if (root.is_discarded())
{
LL_WARNS() << "Failed to parse json string from body:\n" << body << LL_ENDL;
return; // TODO: Should we say something here for the user?
}
std::string viewer_version = llformat("%s (%i)", LLVersionInfo::getShortVersion().c_str(), LLVersionInfo::getBuild());