Do not crash upon corrupted HTTP header.

This addresses the reported assertion by luis thibodeaux.
This commit is contained in:
Aleric Inglewood
2013-01-03 21:06:20 +01:00
parent 17e0c79fe7
commit 639b264d2d
2 changed files with 23 additions and 10 deletions

View File

@@ -308,9 +308,10 @@ LLAtomicU32 Stats::llsd_body_count;
LLAtomicU32 Stats::llsd_body_parse_error;
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)
{
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).
}

View File

@@ -2268,7 +2268,11 @@ void BufferedCurlEasyRequest::setStatusAndReason(U32 status, std::string const&
{
mStatus = status;
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!
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, ' ');
if (pos2 != end) ++pos2;
std::string::iterator pos3 = std::find(pos2, end, '\r');
U32 status;
U32 status = 0;
std::string reason;
if (pos3 != end && std::isdigit(*pos1))
{
status = atoi(&header_line[pos1 - begin]);
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;
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;
}