diff --git a/include/libtorrent/lazy_entry.hpp b/include/libtorrent/lazy_entry.hpp index a49daec15..fa83e7ba3 100644 --- a/include/libtorrent/lazy_entry.hpp +++ b/include/libtorrent/lazy_entry.hpp @@ -425,6 +425,11 @@ namespace libtorrent return boost::system::error_code(e, get_bdecode_category()); } } + + TORRENT_EXTRA_EXPORT char const* parse_int(char const* start + , char const* end, char delimiter, boost::int64_t& val + , bdecode_errors::error_code_enum& ec); + } #endif diff --git a/src/lazy_bdecode.cpp b/src/lazy_bdecode.cpp index eec257456..86963d24b 100644 --- a/src/lazy_bdecode.cpp +++ b/src/lazy_bdecode.cpp @@ -121,7 +121,7 @@ namespace libtorrent std::vector stack; stack.push_back(&ret); - while (start < end) + while (start <= end) { if (stack.empty()) break; // done! diff --git a/src/natpmp.cpp b/src/natpmp.cpp index 8e4c8c3c9..6e04b9a70 100644 --- a/src/natpmp.cpp +++ b/src/natpmp.cpp @@ -240,7 +240,7 @@ int natpmp::add_mapping(protocol_type p, int external_port, int local_port) for (std::vector::iterator m = m_mappings.begin() , end(m_mappings.end()); m != end; ++m) { - std::cout << " ADD MAPPING: " << mapping_index << " [ " + std::cout << " ADD MAPPING: " << mapping_index << " [ " "proto: " << (i->protocol == none ? "none" : i->protocol == tcp ? "tcp" : "udp") << " port: " << i->external_port << " local-port: " << i->local_port @@ -261,7 +261,7 @@ void natpmp::try_next_mapping(int i, mutex::scoped_lock& l) for (std::vector::iterator m = m_mappings.begin() , end(m_mappings.end()); m != end; ++m) { - std::cout << " " << (m - m_mappings.begin()) << " [ " + std::cout << " " << (m - m_mappings.begin()) << " [ " "proto: " << (m->protocol == none ? "none" : m->protocol == tcp ? "tcp" : "udp") << " port: " << m->external_port << " local-port: " << m->local_port diff --git a/test/test_bencoding.cpp b/test/test_bencoding.cpp index a73c704bc..faea07d06 100644 --- a/test/test_bencoding.cpp +++ b/test/test_bencoding.cpp @@ -202,7 +202,6 @@ int test_main() , get_bdecode_category())); } - // test integers that don't fit in 64 bits { char b[] = "i18446744073709551615e"; @@ -262,12 +261,193 @@ int test_main() TEST_CHECK(ret == -1); } + // test the depth limit + { + char b[2048]; + for (int i = 0; i < 1024; ++i) + b[i]= 'l'; + + for (int i = 1024; i < 2048; ++i) + b[i]= 'e'; + + // 1024 levels nested lists + + lazy_entry e; + error_code ec; + int ret = lazy_bdecode(b, b + sizeof(b), e, ec); + TEST_CHECK(ret != 0); + TEST_EQUAL(ec, error_code(bdecode_errors::depth_exceeded + , get_bdecode_category())); + } + + // test the item limit + { + char b[10240]; + b[0] = 'l'; + int i = 1; + for (i = 1; i < 10239; i += 2) + memcpy(&b[i], "0:", 2); + b[i] = 'e'; + + lazy_entry e; + error_code ec; + int ret = lazy_bdecode(b, b + i + 1, e, ec, NULL, 1000, 1000); + TEST_CHECK(ret != 0); + TEST_EQUAL(ec, error_code(bdecode_errors::limit_exceeded + , get_bdecode_category())); + } + + // test unexpected EOF + { + char b[] = "l2:.."; // expected terminating 'e' + + lazy_entry e; + error_code ec; + int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, NULL); + TEST_CHECK(ret != 0); + printf("%s\n", print_entry(e).c_str()); + TEST_EQUAL(ec, error_code(bdecode_errors::unexpected_eof + , get_bdecode_category())); + } + + // test unexpected EOF (really expected terminator) + { + char b[] = "l2:..0"; // expected terminating 'e' instead of '0' + + lazy_entry e; + error_code ec; + int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, NULL); + TEST_CHECK(ret != 0); + printf("%s\n", print_entry(e).c_str()); + TEST_EQUAL(ec, error_code(bdecode_errors::unexpected_eof + , get_bdecode_category())); + } + + // test expected string + { + char b[] = "di2ei0ee"; + // expected string (dict keys must be strings) + + lazy_entry e; + error_code ec; + int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, NULL); + TEST_CHECK(ret != 0); + printf("%s\n", print_entry(e).c_str()); + TEST_EQUAL(ec, error_code(bdecode_errors::expected_string + , get_bdecode_category())); + } + + // test unexpected EOF while parsing dict key + { + char b[] = "d1000:..e"; + + lazy_entry e; + error_code ec; + int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, NULL); + TEST_CHECK(ret != 0); + printf("%s\n", print_entry(e).c_str()); + TEST_EQUAL(ec, error_code(bdecode_errors::unexpected_eof + , get_bdecode_category())); + } + + // test unexpected EOF while parsing dict key + { + char b[] = "d1000:"; + + lazy_entry e; + error_code ec; + int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, NULL); + TEST_CHECK(ret != 0); + printf("%s\n", print_entry(e).c_str()); + TEST_EQUAL(ec, error_code(bdecode_errors::unexpected_eof + , get_bdecode_category())); + } + + // test unexpected EOF while parsing dict key + { + char b[] = "d1000:"; + + lazy_entry e; + error_code ec; + int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, NULL); + TEST_CHECK(ret != 0); + printf("%s\n", print_entry(e).c_str()); + TEST_EQUAL(ec, error_code(bdecode_errors::unexpected_eof + , get_bdecode_category())); + } + + // test unexpected EOF while parsing int + { + char b[] = "i"; + + lazy_entry e; + error_code ec; + int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, NULL); + TEST_CHECK(ret != 0); + printf("%s\n", print_entry(e).c_str()); + TEST_EQUAL(ec, error_code(bdecode_errors::unexpected_eof + , get_bdecode_category())); + } + + // test unexpected EOF while parsing int + { + char b[] = "i10"; + + lazy_entry e; + error_code ec; + int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, NULL); + TEST_CHECK(ret != 0); + printf("%s\n", print_entry(e).c_str()); + TEST_EQUAL(ec, error_code(bdecode_errors::unexpected_eof + , get_bdecode_category())); + } + + + // test expected colon + { + char b[] = "d1000"; + + lazy_entry e; + error_code ec; + int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec, NULL); + TEST_CHECK(ret != 0); + printf("%s\n", print_entry(e).c_str()); + TEST_EQUAL(ec, error_code(bdecode_errors::expected_colon + , get_bdecode_category())); + } + { unsigned char buf[] = { 0x44 , 0x91 , 0x3a }; entry ent = bdecode(buf, buf + sizeof(buf)); TEST_CHECK(ent == entry()); } + // test parse_int + { + char b[] = "1234567890e"; + boost::int64_t val = 0; + bdecode_errors::error_code_enum ec; + char const* e = parse_int(b, b + sizeof(b)-1, 'e', val, ec); + TEST_EQUAL(val, 1234567890); + TEST_EQUAL(e, b + sizeof(b) - 2); + } + + { + char b[] = "9223372036854775808:"; + boost::int64_t val = 0; + bdecode_errors::error_code_enum ec; + char const* e = parse_int(b, b + sizeof(b)-1, ':', val, ec); + TEST_CHECK(ec == bdecode_errors::overflow); + } + + { + char b[] = "928"; + boost::int64_t val = 0; + bdecode_errors::error_code_enum ec; + char const* e = parse_int(b, b + sizeof(b)-1, ':', val, ec); + TEST_CHECK(ec == bdecode_errors::expected_colon); + } + return 0; }