merged RC_1_1 into master

This commit is contained in:
arvidn 2016-06-04 14:09:19 -04:00
commit edf9f8070d
4 changed files with 156 additions and 24 deletions

View File

@ -21,6 +21,7 @@
1.1.1 release
* fixed crash on invalid input in http_parser
* upgraded to libtommath 1.0
* fixed parsing of IPv6 endpoint with invalid port character separator
* added limited support for new x.pe parameter from BEP 9

View File

@ -313,7 +313,7 @@ namespace libtorrent
std::string name;
// the path where the torrent is or will be stored.
//
//
// .. note::
// On windows this path (and other paths) are interpreted as UNC
// paths. This means they must use backslashes as directory separators
@ -366,6 +366,12 @@ namespace libtorrent
// flags controlling aspects of this torrent and how it's added. See
// flags_t for details.
//
// .. note::
// The ``flags`` field is initialized with default flags by the
// constructor. In order to preserve default behavior when clearing or
// setting other flags, make sure to bitwise OR or in a flag or bitwise
// AND the inverse of a flag to clear it.
boost::uint64_t flags;
// set this to the info hash of the torrent to add in case the info-hash

View File

@ -174,6 +174,7 @@ restart_response:
if (m_state == read_status)
{
TORRENT_ASSERT(!m_finished);
TORRENT_ASSERT(pos <= recv_buffer.end);
char const* newline = std::find(pos, recv_buffer.end, '\n');
// if we don't have a full line yet, wait.
if (newline == recv_buffer.end)
@ -194,6 +195,7 @@ restart_response:
char const* line = pos;
++newline;
TORRENT_ASSERT(newline >= pos);
int incoming = int(newline - pos);
m_recv_pos += incoming;
boost::get<1>(ret) += newline - (m_recv_buffer.begin + start_pos);
@ -227,6 +229,7 @@ restart_response:
if (m_state == read_header)
{
TORRENT_ASSERT(!m_finished);
TORRENT_ASSERT(pos <= recv_buffer.end);
char const* newline = std::find(pos, recv_buffer.end, '\n');
std::string line;
@ -277,6 +280,12 @@ restart_response:
if (name == "content-length")
{
m_content_length = strtoll(value.c_str(), 0, 10);
if (m_content_length < 0)
{
m_state = error_state;
error = true;
return ret;
}
}
else if (name == "connection")
{
@ -294,12 +303,24 @@ restart_response:
if (string_begins_no_case("bytes ", ptr)) ptr += 6;
char* end;
m_range_start = strtoll(ptr, &end, 10);
if (m_range_start < 0)
{
m_state = error_state;
error = true;
return ret;
}
if (end == ptr) success = false;
else if (*end != '-') success = false;
else
{
ptr = end + 1;
m_range_end = strtoll(ptr, &end, 10);
if (m_range_end < 0)
{
m_state = error_state;
error = true;
return ret;
}
if (end == ptr) success = false;
}
@ -318,6 +339,7 @@ restart_response:
}
TORRENT_ASSERT(m_recv_pos <= recv_buffer.left());
TORRENT_ASSERT(pos <= recv_buffer.end);
newline = std::find(pos, recv_buffer.end, '\n');
}
boost::get<1>(ret) += newline - (m_recv_buffer.begin + start_pos);
@ -347,6 +369,12 @@ restart_response:
int header_size;
if (parse_chunk_header(buf, &chunk_size, &header_size))
{
if (chunk_size < 0)
{
m_state = error_state;
error = true;
return ret;
}
if (chunk_size > 0)
{
std::pair<boost::int64_t, boost::int64_t> chunk_range(m_cur_chunk_end + header_size
@ -420,6 +448,7 @@ restart_response:
bool http_parser::parse_chunk_header(buffer::const_interval buf
, boost::int64_t* chunk_size, int* header_size)
{
TORRENT_ASSERT(buf.begin <= buf.end);
char const* pos = buf.begin;
// ignore one optional new-line. This is since each chunk
@ -430,6 +459,7 @@ restart_response:
if (pos < buf.end && pos[0] == '\n') ++pos;
if (pos == buf.end) return false;
TORRENT_ASSERT(pos <= buf.end);
char const* newline = std::find(pos, buf.end, '\n');
if (newline == buf.end) return false;
++newline;
@ -442,6 +472,8 @@ restart_response:
// first, read the chunk length
*chunk_size = strtoll(pos, 0, 16);
if (*chunk_size < 0) return true;
if (*chunk_size != 0)
{
*header_size = newline - buf.begin;

View File

@ -361,29 +361,6 @@ TORRENT_TEST(http_parser)
TEST_EQUAL(parser.headers().find("test2")->second, "bar");
}
// test chunked encoding
parser.reset();
char const* chunked_input =
"HTTP/1.1 200 OK\r\n"
"Transfer-Encoding: chunked\r\n"
"Content-Type: text/plain\r\n"
"\r\n"
"4\r\ntest\r\n4\r\n1234\r\n10\r\n0123456789abcdef\r\n"
"0\r\n\r\n";
received = feed_bytes(parser, chunked_input);
TEST_EQUAL(strlen(chunked_input), 24 + 94)
TEST_CHECK(received == make_tuple(24, 94, false));
TEST_CHECK(parser.finished());
char mutable_buffer[100];
memcpy(mutable_buffer, parser.get_body().begin, parser.get_body().left());
int len = parser.collapse_chunk_headers(mutable_buffer, parser.get_body().left());
TEST_CHECK(std::equal(mutable_buffer, mutable_buffer + len, "test12340123456789abcdef"));
// test url parsing
error_code ec;
@ -476,3 +453,119 @@ TORRENT_TEST(http_parser)
TEST_EQUAL(is_redirect(400), false);
}
TORRENT_TEST(chunked_encoding)
{
char const* chunked_input =
"HTTP/1.1 200 OK\r\n"
"Transfer-Encoding: chunked\r\n"
"Content-Type: text/plain\r\n"
"\r\n"
"4\r\ntest\r\n4\r\n1234\r\n10\r\n0123456789abcdef\r\n"
"0\r\n\r\n";
http_parser parser;
boost::tuple<int, int, bool> const received
= feed_bytes(parser, chunked_input);
TEST_EQUAL(strlen(chunked_input), 24 + 94)
TEST_CHECK(received == make_tuple(24, 94, false));
TEST_CHECK(parser.finished());
char mutable_buffer[100];
memcpy(mutable_buffer, parser.get_body().begin, parser.get_body().left());
int len = parser.collapse_chunk_headers(mutable_buffer, parser.get_body().left());
TEST_CHECK(std::equal(mutable_buffer, mutable_buffer + len, "test12340123456789abcdef"));
}
TORRENT_TEST(invalid_content_length)
{
char const* chunked_input =
"HTTP/1.1 200 OK\r\n"
"Transfer-Encoding: chunked\r\n"
"Content-Length: -45345\r\n"
"\r\n";
http_parser parser;
boost::tuple<int, int, bool> const received
= feed_bytes(parser, chunked_input);
TEST_CHECK(boost::get<2>(received) == true);
}
TORRENT_TEST(invalid_chunked)
{
char const* chunked_input =
"HTTP/1.1 200 OK\r\n"
"Transfer-Encoding: chunked\r\n"
"\r\n"
"-53465234545\r\n"
"foobar";
http_parser parser;
boost::tuple<int, int, bool> const received
= feed_bytes(parser, chunked_input);
TEST_CHECK(boost::get<2>(received) == true);
}
TORRENT_TEST(invalid_content_range_start)
{
char const* chunked_input =
"HTTP/1.1 206 OK\n"
"Content-Range: bYTes -3-4\n"
"\n";
http_parser parser;
boost::tuple<int, int, bool> const received
= feed_bytes(parser, chunked_input);
TEST_CHECK(boost::get<2>(received) == true);
}
TORRENT_TEST(invalid_content_range_end)
{
char const* chunked_input =
"HTTP/1.1 206 OK\n"
"Content-Range: bYTes 3--434\n"
"\n";
http_parser parser;
boost::tuple<int, int, bool> const received
= feed_bytes(parser, chunked_input);
TEST_CHECK(boost::get<2>(received) == true);
}
TORRENT_TEST(invalid_chunk_afl)
{
boost::uint8_t const invalid_chunked_input[] = {
0x48, 0x6f, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, // HoTP/1.1 200 OK
0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d, // Cont-Length: 20
0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x2d, 0x4c, 0x65, // Contente: tn
0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x32, 0x30, // Transfer-Encoding: chunked
0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, //
0x74, 0x65, 0x3a, 0x20, 0x74, 0x6e, 0x0d, 0x0a, //
0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, //
0x2d, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, // -89abc9abcdef
0x67, 0x3a, 0x20, 0x63, 0x68, 0x75, 0x6e, 0x6b, // <20>
0x65, 0x64, 0x0d, 0x0a, 0x0d, 0x0d, 0x0a, 0x0d, // T<><54><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>def
0x0a, 0x0a, 0x2d, 0x38, 0x39, 0x61, 0x62, 0x63, // <20>
0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x0d, // T<><54><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>est-headyr: foobar
0x0a, 0xd6, 0x0d, 0x0a, 0x54, 0xbd, 0xbd, 0xbd,
0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x64,
0x65, 0x66, 0x0d, 0x0a, 0xd6, 0x0d, 0x0a, 0x54,
0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
0xbd, 0xbd, 0xbd, 0x65, 0x73, 0x74, 0x2d, 0x68,
0x65, 0x61, 0x64, 0x79, 0x72, 0x3a, 0x20, 0x66,
0x6f, 0x6f, 0x62, 0x61, 0x72, 0x0d, 0x0a, 0x0d,
0x0a, 0x00
};
http_parser parser;
boost::tuple<int, int, bool> const received
= feed_bytes(parser, reinterpret_cast<char const*>(invalid_chunked_input));
TEST_CHECK(boost::get<2>(received) == true);
}