merged bdecode fix from RC_0_16

This commit is contained in:
Arvid Norberg 2014-04-04 03:21:15 +00:00
parent a63e074274
commit 91799025f2
6 changed files with 125 additions and 40 deletions

View File

@ -45,6 +45,8 @@
* fix uTP edge case where udp socket buffer fills up * fix uTP edge case where udp socket buffer fills up
* fix nagle implementation in uTP * fix nagle implementation in uTP
* improve error checking in lazy_bdecode
0.16.16 release 0.16.16 release
* add missing add_files overload to the python bindings * add missing add_files overload to the python bindings

View File

@ -431,6 +431,8 @@ namespace libtorrent
depth_exceeded, depth_exceeded,
// bencoded item count limit exceeded // bencoded item count limit exceeded
limit_exceeded, limit_exceeded,
// integer overflow
overflow,
#endif #endif
// the number of error codes // the number of error codes

View File

@ -412,6 +412,8 @@ namespace libtorrent
depth_exceeded, depth_exceeded,
// bencoded item count limit exceeded // bencoded item count limit exceeded
limit_exceeded, limit_exceeded,
// integer overflow
overflow,
// the number of error codes // the number of error codes
error_code_max error_code_max

View File

@ -266,6 +266,7 @@ namespace libtorrent
"expected value (list, dict, int or string) in bencoded string", "expected value (list, dict, int or string) in bencoded string",
"bencoded nesting depth exceeded", "bencoded nesting depth exceeded",
"bencoded item count limit exceeded", "bencoded item count limit exceeded",
"integer overflow",
#endif #endif
}; };
if (ev < 0 || ev >= int(sizeof(msgs)/sizeof(msgs[0]))) if (ev < 0 || ev >= int(sizeof(msgs)/sizeof(msgs[0])))

View File

@ -71,8 +71,19 @@ namespace libtorrent
ec = bdecode_errors::expected_string; ec = bdecode_errors::expected_string;
return start; return start;
} }
if (val > INT64_MAX / 10)
{
ec = bdecode_errors::overflow;
return start;
}
val *= 10; val *= 10;
val += *start - '0'; int digit = *start - '0';
if (val > INT64_MAX - digit)
{
ec = bdecode_errors::overflow;
return start;
}
val += digit;
++start; ++start;
} }
if (*start != delimiter) if (*start != delimiter)
@ -139,6 +150,9 @@ namespace libtorrent
if (start + len + 1 > end) if (start + len + 1 > end)
TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof); TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof);
if (len < 0)
TORRENT_FAIL_BDECODE(bdecode_errors::overflow);
++start; ++start;
if (start == end) TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof); if (start == end) TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof);
lazy_entry* ent = top->dict_append(start); lazy_entry* ent = top->dict_append(start);
@ -201,6 +215,9 @@ namespace libtorrent
TORRENT_FAIL_BDECODE(e); TORRENT_FAIL_BDECODE(e);
if (start + len + 1 > end) if (start + len + 1 > end)
TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof); TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof);
if (len < 0)
TORRENT_FAIL_BDECODE(bdecode_errors::overflow);
++start; ++start;
top->construct_string(start, int(len)); top->construct_string(start, int(len));
stack.pop_back(); stack.pop_back();
@ -220,9 +237,9 @@ namespace libtorrent
bool negative = false; bool negative = false;
if (*m_data.start == '-') negative = true; if (*m_data.start == '-') negative = true;
bdecode_errors::error_code_enum ec = bdecode_errors::no_error; bdecode_errors::error_code_enum ec = bdecode_errors::no_error;
parse_int(negative?m_data.start+1:m_data.start parse_int(m_data.start + negative
, m_data.start + m_size, 'e', val, ec); , m_data.start + m_size, 'e', val, ec);
TORRENT_ASSERT(!ec); if (ec) return 0;
if (negative) val = -val; if (negative) val = -val;
return val; return val;
} }
@ -628,6 +645,7 @@ namespace libtorrent
"expected value (list, dict, int or string) in bencoded string", "expected value (list, dict, int or string) in bencoded string",
"bencoded nesting depth exceeded", "bencoded nesting depth exceeded",
"bencoded item count limit exceeded", "bencoded item count limit exceeded",
"integer overflow",
}; };
if (ev < 0 || ev >= int(sizeof(msgs)/sizeof(msgs[0]))) if (ev < 0 || ev >= int(sizeof(msgs)/sizeof(msgs[0])))
return "Unknown error"; return "Unknown error";

View File

@ -109,13 +109,13 @@ int test_main()
lazy_entry e; lazy_entry e;
error_code ec; error_code ec;
int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec); int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
TORRENT_ASSERT(ret == 0); TEST_CHECK(ret == 0);
printf("%s\n", print_entry(e).c_str()); printf("%s\n", print_entry(e).c_str());
std::pair<const char*, int> section = e.data_section(); std::pair<const char*, int> section = e.data_section();
TORRENT_ASSERT(std::memcmp(b, section.first, section.second) == 0); TEST_CHECK(std::memcmp(b, section.first, section.second) == 0);
TORRENT_ASSERT(section.second == sizeof(b) - 1); TEST_CHECK(section.second == sizeof(b) - 1);
TORRENT_ASSERT(e.type() == lazy_entry::int_t); TEST_CHECK(e.type() == lazy_entry::int_t);
TORRENT_ASSERT(e.int_value() == 12453); TEST_CHECK(e.int_value() == 12453);
} }
{ {
@ -123,14 +123,14 @@ int test_main()
lazy_entry e; lazy_entry e;
error_code ec; error_code ec;
int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec); int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
TORRENT_ASSERT(ret == 0); TEST_CHECK(ret == 0);
printf("%s\n", print_entry(e).c_str()); printf("%s\n", print_entry(e).c_str());
std::pair<const char*, int> section = e.data_section(); std::pair<const char*, int> section = e.data_section();
TORRENT_ASSERT(std::memcmp(b, section.first, section.second) == 0); TEST_CHECK(std::memcmp(b, section.first, section.second) == 0);
TORRENT_ASSERT(section.second == sizeof(b) - 1); TEST_CHECK(section.second == sizeof(b) - 1);
TORRENT_ASSERT(e.type() == lazy_entry::string_t); TEST_CHECK(e.type() == lazy_entry::string_t);
TORRENT_ASSERT(e.string_value() == std::string("abcdefghijklmnopqrstuvwxyz")); TEST_CHECK(e.string_value() == std::string("abcdefghijklmnopqrstuvwxyz"));
TORRENT_ASSERT(e.string_length() == 26); TEST_CHECK(e.string_length() == 26);
} }
{ {
@ -138,21 +138,21 @@ int test_main()
lazy_entry e; lazy_entry e;
error_code ec; error_code ec;
int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec); int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
TORRENT_ASSERT(ret == 0); TEST_CHECK(ret == 0);
printf("%s\n", print_entry(e).c_str()); printf("%s\n", print_entry(e).c_str());
std::pair<const char*, int> section = e.data_section(); std::pair<const char*, int> section = e.data_section();
TORRENT_ASSERT(std::memcmp(b, section.first, section.second) == 0); TEST_CHECK(std::memcmp(b, section.first, section.second) == 0);
TORRENT_ASSERT(section.second == sizeof(b) - 1); TEST_CHECK(section.second == sizeof(b) - 1);
TORRENT_ASSERT(e.type() == lazy_entry::list_t); TEST_CHECK(e.type() == lazy_entry::list_t);
TORRENT_ASSERT(e.list_size() == 2); TEST_CHECK(e.list_size() == 2);
TORRENT_ASSERT(e.list_at(0)->type() == lazy_entry::int_t); TEST_CHECK(e.list_at(0)->type() == lazy_entry::int_t);
TORRENT_ASSERT(e.list_at(1)->type() == lazy_entry::string_t); TEST_CHECK(e.list_at(1)->type() == lazy_entry::string_t);
TORRENT_ASSERT(e.list_at(0)->int_value() == 12453); TEST_CHECK(e.list_at(0)->int_value() == 12453);
TORRENT_ASSERT(e.list_at(1)->string_value() == std::string("aaa")); TEST_CHECK(e.list_at(1)->string_value() == std::string("aaa"));
TORRENT_ASSERT(e.list_at(1)->string_length() == 3); TEST_CHECK(e.list_at(1)->string_length() == 3);
section = e.list_at(1)->data_section(); section = e.list_at(1)->data_section();
TORRENT_ASSERT(std::memcmp("3:aaa", section.first, section.second) == 0); TEST_CHECK(std::memcmp("3:aaa", section.first, section.second) == 0);
TORRENT_ASSERT(section.second == 5); TEST_CHECK(section.second == 5);
} }
{ {
@ -160,22 +160,82 @@ int test_main()
lazy_entry e; lazy_entry e;
error_code ec; error_code ec;
int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec); int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
TORRENT_ASSERT(ret == 0); TEST_CHECK(ret == 0);
printf("%s\n", print_entry(e).c_str()); printf("%s\n", print_entry(e).c_str());
std::pair<const char*, int> section = e.data_section(); std::pair<const char*, int> section = e.data_section();
TORRENT_ASSERT(std::memcmp(b, section.first, section.second) == 0); TEST_CHECK(std::memcmp(b, section.first, section.second) == 0);
TORRENT_ASSERT(section.second == sizeof(b) - 1); TEST_CHECK(section.second == sizeof(b) - 1);
TORRENT_ASSERT(e.type() == lazy_entry::dict_t); TEST_CHECK(e.type() == lazy_entry::dict_t);
TORRENT_ASSERT(e.dict_size() == 4); TEST_CHECK(e.dict_size() == 4);
TORRENT_ASSERT(e.dict_find("a")->type() == lazy_entry::int_t); TEST_CHECK(e.dict_find("a")->type() == lazy_entry::int_t);
TORRENT_ASSERT(e.dict_find("a")->int_value() == 12453); TEST_CHECK(e.dict_find("a")->int_value() == 12453);
TORRENT_ASSERT(e.dict_find("b")->type() == lazy_entry::string_t); TEST_CHECK(e.dict_find("b")->type() == lazy_entry::string_t);
TORRENT_ASSERT(e.dict_find("b")->string_value() == std::string("aaa")); TEST_CHECK(e.dict_find("b")->string_value() == std::string("aaa"));
TORRENT_ASSERT(e.dict_find("b")->string_length() == 3); TEST_CHECK(e.dict_find("b")->string_length() == 3);
TORRENT_ASSERT(e.dict_find("c")->type() == lazy_entry::string_t); TEST_CHECK(e.dict_find("c")->type() == lazy_entry::string_t);
TORRENT_ASSERT(e.dict_find("c")->string_value() == std::string("bbb")); TEST_CHECK(e.dict_find("c")->string_value() == std::string("bbb"));
TORRENT_ASSERT(e.dict_find("c")->string_length() == 3); TEST_CHECK(e.dict_find("c")->string_length() == 3);
TORRENT_ASSERT(e.dict_find_string_value("X") == "0123456789"); TEST_CHECK(e.dict_find_string_value("X") == "0123456789");
}
// test strings with negative length-prefix
{
char b[] = "-10:foobar";
lazy_entry e;
error_code ec;
int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
TEST_CHECK(ret != 0);
printf("%s\n", print_entry(e).c_str());
TEST_CHECK(ec == error_code(bdecode_errors::expected_value
, get_bdecode_category()));
}
// test strings with overflow length-prefix
{
char b[] = "18446744073709551615:foobar";
lazy_entry e;
error_code ec;
int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
TEST_CHECK(ret != 0);
printf("%s\n", print_entry(e).c_str());
TEST_CHECK(ec == error_code(bdecode_errors::overflow
, get_bdecode_category()));
}
// test integers that don't fit in 64 bits
{
char b[] = "i18446744073709551615e";
lazy_entry e;
error_code ec;
int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
TEST_CHECK(ret == 0);
printf("%s\n", print_entry(e).c_str());
// the lazy aspect makes this overflow when asking for
// the value. turning it to zero.
TEST_CHECK(e.int_value() == 0);
}
// test integers that just exactly fit in 64 bits
{
char b[] = "i9223372036854775807e";
lazy_entry e;
error_code ec;
int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
TEST_CHECK(ret == 0);
printf("%s\n", print_entry(e).c_str());
TEST_CHECK(e.int_value() == 9223372036854775807LL);
}
// test integers that just exactly fit in 64 bits
{
char b[] = "i-9223372036854775807e";
lazy_entry e;
error_code ec;
int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
TEST_CHECK(ret == 0);
printf("%s\n", print_entry(e).c_str());
TEST_CHECK(e.int_value() == -9223372036854775807LL);
} }
// test invalid encoding // test invalid encoding