Do not crash upon corrupted HTTP header.
This addresses the reported assertion by luis thibodeaux.
This commit is contained in:
@@ -308,9 +308,10 @@ LLAtomicU32 Stats::llsd_body_count;
|
|||||||
LLAtomicU32 Stats::llsd_body_parse_error;
|
LLAtomicU32 Stats::llsd_body_parse_error;
|
||||||
LLAtomicU32 Stats::raw_body_count;
|
LLAtomicU32 Stats::raw_body_count;
|
||||||
|
|
||||||
|
// Called from BufferedCurlEasyRequest::setStatusAndReason.
|
||||||
|
// The only allowed values for 'status' are S <= status < S+20, where S={100,200,300,400,500}.
|
||||||
U32 Stats::status2index(U32 status)
|
U32 Stats::status2index(U32 status)
|
||||||
{
|
{
|
||||||
llassert_always(status >= 100 && status < 600 && (status % 100) < 20); // Max value 519.
|
|
||||||
return (status - 100) / 100 * 20 + status % 100; // Returns 0..99 (for status 100..519).
|
return (status - 100) / 100 * 20 + status % 100; // Returns 0..99 (for status 100..519).
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2268,7 +2268,11 @@ void BufferedCurlEasyRequest::setStatusAndReason(U32 status, std::string const&
|
|||||||
{
|
{
|
||||||
mStatus = status;
|
mStatus = status;
|
||||||
mReason = reason;
|
mReason = reason;
|
||||||
AICurlInterface::Stats::status_count[AICurlInterface::Stats::status2index(mStatus)]++;
|
if (status >= 100 && status < 600 && (status % 100) < 20)
|
||||||
|
{
|
||||||
|
// Only count statistic for sane values.
|
||||||
|
AICurlInterface::Stats::status_count[AICurlInterface::Stats::status2index(mStatus)]++;
|
||||||
|
}
|
||||||
|
|
||||||
// Sanity check. If the server replies with a redirect status then we better have that option turned on!
|
// Sanity check. If the server replies with a redirect status then we better have that option turned on!
|
||||||
if ((status >= 300 && status < 400) && mResponder && !mResponder->redirect_status_ok())
|
if ((status >= 300 && status < 400) && mResponder && !mResponder->redirect_status_ok())
|
||||||
@@ -2419,23 +2423,31 @@ size_t BufferedCurlEasyRequest::curlHeaderCallback(char* data, size_t size, size
|
|||||||
std::string::iterator pos2 = std::find(pos1, end, ' ');
|
std::string::iterator pos2 = std::find(pos1, end, ' ');
|
||||||
if (pos2 != end) ++pos2;
|
if (pos2 != end) ++pos2;
|
||||||
std::string::iterator pos3 = std::find(pos2, end, '\r');
|
std::string::iterator pos3 = std::find(pos2, end, '\r');
|
||||||
U32 status;
|
U32 status = 0;
|
||||||
std::string reason;
|
std::string reason;
|
||||||
if (pos3 != end && std::isdigit(*pos1))
|
if (pos3 != end && std::isdigit(*pos1))
|
||||||
{
|
{
|
||||||
status = atoi(&header_line[pos1 - begin]);
|
status = atoi(&header_line[pos1 - begin]);
|
||||||
reason.assign(pos2, pos3);
|
reason.assign(pos2, pos3);
|
||||||
}
|
}
|
||||||
else
|
if (!(status >= 100 && status < 600 && (status % 100) < 20)) // Sanity check on the decoded status.
|
||||||
{
|
{
|
||||||
|
if (status == 0)
|
||||||
|
{
|
||||||
|
reason = "Header parse error.";
|
||||||
|
llwarns << "Received broken header line from server: \"" << header << "\"" << llendl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reason = "Unexpected HTTP status.";
|
||||||
|
llwarns << "Received unexpected status value from server (" << status << "): \"" << header << "\"" << llendl;
|
||||||
|
}
|
||||||
|
// Either way, this status value is not understood (or taken into account).
|
||||||
|
// Set it to internal error so that the rest of code treats it as an error.
|
||||||
status = HTTP_INTERNAL_ERROR;
|
status = HTTP_INTERNAL_ERROR;
|
||||||
reason = "Header parse error.";
|
|
||||||
llwarns << "Received broken header line from server: \"" << header << "\"" << llendl;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
self_w->received_HTTP_header();
|
|
||||||
self_w->setStatusAndReason(status, reason);
|
|
||||||
}
|
}
|
||||||
|
self_w->received_HTTP_header();
|
||||||
|
self_w->setStatusAndReason(status, reason);
|
||||||
return header_len;
|
return header_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user