Skip to content

Commit aa2a0b9

Browse files
committed
Fixed up some http_listener linux request parsing issues.
1. If an invalid URI was presented during parsing it would crash the server. 2. Fixed parsing of HTTP headers to not allow a header that starts with a colon since it is invalid. 3. Fixed the else error case branch when parsing HTTP headers, where the rest of the request wasn't being consumed before responding. This results in a hang until timeout occurs. 4. Removed some dead code in a couple of error cases. 5. Fixed some try/catch whitespace bracket locations.
1 parent e04b8e4 commit aa2a0b9

File tree

1 file changed

+27
-20
lines changed

1 file changed

+27
-20
lines changed

Release/src/http/listener/http_linux_server.cpp

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ void connection::handle_http_line(const boost::system::error_code& ec)
158158
std::string http_path_and_version;
159159
std::getline(request_stream, http_path_and_version);
160160
const size_t VersionPortionSize = sizeof(" HTTP/1.1\r") - 1;
161-
161+
162162
// Make sure path and version is long enough to contain the HTTP version
163163
if(http_path_and_version.size() < VersionPortionSize + 2)
164164
{
@@ -176,8 +176,18 @@ void connection::handle_http_line(const boost::system::error_code& ec)
176176

177177
// Get the path - remove the version portion and prefix space
178178
builder.append_path(http_path_and_version.substr(1, http_path_and_version.size() - VersionPortionSize - 1));
179-
m_request.set_request_uri(builder.to_uri());
180-
179+
try
180+
{
181+
m_request.set_request_uri(builder.to_uri());
182+
}
183+
catch(const uri_exception &e)
184+
{
185+
m_request.reply(status_codes::BadRequest, e.what());
186+
m_close = true;
187+
do_response(true);
188+
return;
189+
}
190+
181191
// Get the version
182192
std::string http_version = http_path_and_version.substr(http_path_and_version.size() - VersionPortionSize + 1, VersionPortionSize - 2);
183193
// if HTTP version is 1.0 then disable pipelining
@@ -197,10 +207,10 @@ void connection::handle_headers()
197207
while (std::getline(request_stream, header) && header != "\r")
198208
{
199209
auto colon = header.find(':');
200-
if (colon != std::string::npos)
210+
if (colon != std::string::npos && colon != 0)
201211
{
202212
auto name = header.substr(0, colon);
203-
auto value = header.substr(colon+1, header.length() - (colon+1)); // also exclude '\r'
213+
auto value = header.substr(colon + 1, header.length() - (colon + 1)); // also exclude '\r'
204214
http::details::trim_whitespace(name);
205215
http::details::trim_whitespace(value);
206216

@@ -217,7 +227,8 @@ void connection::handle_headers()
217227
else
218228
{
219229
m_request.reply(status_codes::BadRequest);
220-
do_response();
230+
m_close = true;
231+
do_response(true);
221232
return;
222233
}
223234
}
@@ -290,7 +301,8 @@ void connection::handle_chunked_body(const boost::system::error_code& ec, int to
290301
auto writebuf = m_request._get_impl()->outstream().streambuf();
291302
writebuf.putn(buffer_cast<const uint8_t *>(m_request_buf.data()), toWrite).then([=](pplx::task<size_t> writeChunkTask)
292303
{
293-
try {
304+
try
305+
{
294306
writeChunkTask.get();
295307
} catch (...) {
296308
m_request._reply_if_not_already(status_codes::InternalError);
@@ -321,7 +333,8 @@ void connection::handle_body(const boost::system::error_code& ec)
321333
writebuf.putn(boost::asio::buffer_cast<const uint8_t*>(m_request_buf.data()), std::min(m_request_buf.size(), m_read_size - m_read)).then([=](pplx::task<size_t> writtenSizeTask)
322334
{
323335
size_t writtenSize = 0;
324-
try {
336+
try
337+
{
325338
writtenSize = writtenSizeTask.get();
326339
} catch (...) {
327340
m_request._reply_if_not_already(status_codes::InternalError);
@@ -409,21 +422,16 @@ void connection::dispatch_request_to_listener()
409422
catch(const std::exception &e)
410423
{
411424
pListenerLock->unlock();
412-
std::ostringstream str_stream;
413-
str_stream << "Error: a std::exception was thrown out of http_listener handle: " << e.what();
414-
415425
m_request._reply_if_not_already(status_codes::InternalError);
416426
}
417427
catch(...)
418428
{
419429
pListenerLock->unlock();
420-
421430
m_request._reply_if_not_already(status_codes::InternalError);
422431
}
423432
}
424433

425-
if (--m_refs == 0)
426-
delete this;
434+
if (--m_refs == 0) delete this;
427435
}
428436

429437
void connection::request_data_avail(size_t size)
@@ -446,13 +454,11 @@ void connection::do_response(bool bad_request)
446454
}
447455
catch(const std::exception& ex)
448456
{
449-
std::ostringstream str_stream;
450-
str_stream << "Error in listener: " << ex.what() << std::endl;
451457
response = http::http_response(status_codes::InternalError);
452458
}
453459
catch(...)
454460
{
455-
response = http::http_response(status_codes::InternalError);
461+
response = http::http_response(status_codes::InternalError);
456462
}
457463

458464
// before sending response, the full incoming message need to be processed.
@@ -536,7 +542,8 @@ void connection::handle_write_chunked_response(http_response response, const boo
536542
readbuf.getn(buffer_cast<uint8_t *>(membuf) + http::details::chunked_encoding::data_offset, ChunkSize).then([=](pplx::task<size_t> actualSizeTask)
537543
{
538544
size_t actualSize = 0;
539-
try {
545+
try
546+
{
540547
actualSize = actualSizeTask.get();
541548
} catch (...) {
542549
return cancel_sending_response_with_error(response, std::current_exception());
@@ -553,7 +560,6 @@ void connection::handle_write_chunked_response(http_response response, const boo
553560
});
554561
}
555562

556-
557563
void connection::handle_write_large_response(http_response response, const boost::system::error_code& ec)
558564
{
559565
if (ec || m_write == m_write_size)
@@ -566,7 +572,8 @@ void connection::handle_write_large_response(http_response response, const boost
566572
readbuf.getn(buffer_cast<uint8_t *>(m_response_buf.prepare(readBytes)), readBytes).then([=](pplx::task<size_t> actualSizeTask)
567573
{
568574
size_t actualSize = 0;
569-
try {
575+
try
576+
{
570577
actualSize = actualSizeTask.get();
571578
} catch (...) {
572579
return cancel_sending_response_with_error(response, std::current_exception());

0 commit comments

Comments
 (0)