summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'net-libs/rb_libtorrent/files/rb_libtorrent-1.0.9-CVE-2016-5301.patch')
-rw-r--r--net-libs/rb_libtorrent/files/rb_libtorrent-1.0.9-CVE-2016-5301.patch289
1 files changed, 289 insertions, 0 deletions
diff --git a/net-libs/rb_libtorrent/files/rb_libtorrent-1.0.9-CVE-2016-5301.patch b/net-libs/rb_libtorrent/files/rb_libtorrent-1.0.9-CVE-2016-5301.patch
new file mode 100644
index 000000000000..19ebeeb2fd98
--- /dev/null
+++ b/net-libs/rb_libtorrent/files/rb_libtorrent-1.0.9-CVE-2016-5301.patch
@@ -0,0 +1,289 @@
+From 22099cec46741417a6fb6df560468eb64655db33 Mon Sep 17 00:00:00 2001
+From: arvidn <arvid@cs.umu.se>
+Date: Sat, 4 Jun 2016 12:49:38 -0400
+Subject: [PATCH] back-port http_parser bugfix
+
+---
+ src/http_parser.cpp | 32 +++++++
+ test/test_http_parser.cpp | 142 ++++++++++++++++++++++++------
+
+diff --git a/src/http_parser.cpp b/src/http_parser.cpp
+index 7664cad..89de739 100644
+--- a/src/http_parser.cpp
++++ b/src/http_parser.cpp
+@@ -151,6 +151,7 @@ namespace libtorrent
+ 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)
+@@ -171,6 +172,7 @@ namespace libtorrent
+
+ 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);
+@@ -204,6 +206,7 @@ namespace libtorrent
+ 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;
+
+@@ -254,6 +257,12 @@ namespace libtorrent
+ 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")
+ {
+@@ -271,12 +280,24 @@ namespace libtorrent
+ 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;
+ }
+
+@@ -295,6 +316,7 @@ namespace libtorrent
+ }
+
+ 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);
+@@ -324,6 +346,12 @@ namespace libtorrent
+ 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<size_type, size_type> chunk_range(m_cur_chunk_end + header_size
+@@ -396,6 +424,7 @@ namespace libtorrent
+ bool http_parser::parse_chunk_header(buffer::const_interval buf
+ , size_type* 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
+@@ -406,6 +435,7 @@ namespace libtorrent
+ 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;
+@@ -418,6 +448,8 @@ namespace libtorrent
+
+ // 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;
+diff --git a/test/test_http_parser.cpp b/test/test_http_parser.cpp
+index 1385e94..0bbb038 100644
+--- a/test/test_http_parser.cpp
++++ b/test/test_http_parser.cpp
+@@ -64,10 +64,13 @@ tuple<int, int, bool> feed_bytes(http_parser& parser, char const* str)
+ ret.get<1>() += protocol;
+ ret.get<2>() |= error;
+ // std::cerr << payload << ", " << protocol << ", " << chunk_size << std::endl;
+- TORRENT_ASSERT(payload + protocol == chunk_size);
++ TORRENT_ASSERT(payload + protocol == chunk_size || error);
++ }
++ if (!ret.get<2>())
++ {
++ TEST_CHECK(prev == make_tuple(0, 0, false) || ret == prev);
++ TEST_EQUAL(ret.get<0>() + ret.get<1>(), strlen(str));
+ }
+- TEST_CHECK(prev == make_tuple(0, 0, false) || ret == prev);
+- TEST_EQUAL(ret.get<0>() + ret.get<1>(), strlen(str));
+ prev = ret;
+ }
+ return ret;
+@@ -316,29 +319,6 @@ int test_main()
+ 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;
+@@ -392,6 +372,116 @@ int test_main()
+ TEST_EQUAL(resolve_redirect_location("http://example.com/a/b", "http://test.com/d")
+ , "http://test.com/d");
+
++ 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"));
++}
++
++{
++ 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);
++}
++
++{
++ 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);
++}
++
++{
++ 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);
++}
++
++{
++ 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);
++}
++
++{
++ 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, // �
++ 0x65, 0x64, 0x0d, 0x0a, 0x0d, 0x0d, 0x0a, 0x0d, // T����������def
++ 0x0a, 0x0a, 0x2d, 0x38, 0x39, 0x61, 0x62, 0x63, // �
++ 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x0d, // T�����������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);
++}
++
+ return 0;
+ }
+