From 33a4e1494100d6104f7ed01b0fb668fa30a7a85c Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Sun, 18 Oct 2015 19:38:36 -0200 Subject: [PATCH] sync lazy_bdecode to 0.16 branch before applying security fix --- libtorrent/include/libtorrent/error_code.hpp | 46 +++++----- libtorrent/include/libtorrent/lazy_entry.hpp | 18 +++- libtorrent/src/error_code.cpp | 36 ++++---- libtorrent/src/lazy_bdecode.cpp | 88 +++++++++++++++++--- 4 files changed, 133 insertions(+), 55 deletions(-) diff --git a/libtorrent/include/libtorrent/error_code.hpp b/libtorrent/include/libtorrent/error_code.hpp index c97a9679..46e1d159 100644 --- a/libtorrent/include/libtorrent/error_code.hpp +++ b/libtorrent/include/libtorrent/error_code.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2008-2012, Arvid Norberg +Copyright (c) 2008, Arvid Norberg All rights reserved. Redistribution and use in source and binary forms, with or without @@ -36,7 +36,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include "libtorrent/config.hpp" -#if defined TORRENT_WINDOWS +#if defined TORRENT_WINDOWS || defined TORRENT_CYGWIN // asio assumes that the windows error codes are defined already #include #endif @@ -50,6 +50,10 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/string_util.hpp" // for allocate_string_copy #include // free +#ifndef BOOST_SYSTEM_NOEXCEPT +#define BOOST_SYSTEM_NOEXCEPT throw() +#endif + namespace libtorrent { @@ -265,6 +269,7 @@ namespace libtorrent expected_value, depth_exceeded, limit_exceeded, + overflow, error_code_max }; @@ -310,20 +315,16 @@ namespace libtorrent #if BOOST_VERSION < 103500 typedef asio::error_code error_code; - // hidden inline asio::error::error_category get_posix_category() { return asio::error::system_category; } - // hidden inline asio::error::error_category get_system_category() { return asio::error::system_category; } - // hidden - boost::system::error_category const& get_libtorrent_category() + inline boost::system::error_category const& get_libtorrent_category() { static ::asio::error::error_category libtorrent_category(20); return libtorrent_category; } - // hidden - boost::system::error_category const& get_http_category() + inline boost::system::error_category const& get_http_category() { static ::asio::error::error_category http_category(21); return http_category; @@ -333,26 +334,26 @@ namespace libtorrent struct TORRENT_EXPORT libtorrent_error_category : boost::system::error_category { - virtual const char* name() const throw(); - virtual std::string message(int ev) const throw(); - virtual boost::system::error_condition default_error_condition(int ev) const throw() - { return boost::system::error_condition(ev, *this); } - }; - - struct TORRENT_EXPORT http_error_category : boost::system::error_category - { - virtual const char* name() const throw(); - virtual std::string message(int ev) const throw(); - virtual boost::system::error_condition default_error_condition(int ev) const throw() + virtual const char* name() const BOOST_SYSTEM_NOEXCEPT; + virtual std::string message(int ev) const BOOST_SYSTEM_NOEXCEPT; + virtual boost::system::error_condition default_error_condition(int ev) const BOOST_SYSTEM_NOEXCEPT { return boost::system::error_condition(ev, *this); } }; TORRENT_EXPORT boost::system::error_category& get_libtorrent_category(); + + struct TORRENT_EXPORT http_error_category : boost::system::error_category + { + virtual const char* name() const BOOST_SYSTEM_NOEXCEPT; + virtual std::string message(int ev) const BOOST_SYSTEM_NOEXCEPT; + virtual boost::system::error_condition default_error_condition(int ev) const BOOST_SYSTEM_NOEXCEPT + { return boost::system::error_condition(ev, *this); } + }; + TORRENT_EXPORT boost::system::error_category& get_http_category(); namespace errors { - // hidden inline boost::system::error_code make_error_code(error_code_enum e) { return boost::system::error_code(e, get_libtorrent_category()); @@ -361,15 +362,14 @@ namespace libtorrent using boost::system::error_code; - // hidden - inline boost::system::error_category const& get_system_category() #if BOOST_VERSION < 104400 + inline boost::system::error_category const& get_system_category() { return boost::system::get_system_category(); } #else + inline boost::system::error_category const& get_system_category() { return boost::system::system_category(); } #endif - // hidden inline boost::system::error_category const& get_posix_category() #if BOOST_VERSION < 103600 { return boost::system::get_posix_category(); } diff --git a/libtorrent/include/libtorrent/lazy_entry.hpp b/libtorrent/include/libtorrent/lazy_entry.hpp index f1bb47ea..44cb11b6 100644 --- a/libtorrent/include/libtorrent/lazy_entry.hpp +++ b/libtorrent/include/libtorrent/lazy_entry.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2003-2012, Arvid Norberg +Copyright (c) 2003, Arvid Norberg All rights reserved. Redistribution and use in source and binary forms, with or without @@ -37,6 +37,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include "libtorrent/config.hpp" #include "libtorrent/assert.hpp" #include "libtorrent/size_type.hpp" @@ -50,6 +51,9 @@ namespace libtorrent { struct lazy_entry; + TORRENT_EXPORT char const* parse_int(char const* start, char const* end + , char delimiter, boost::int64_t& val); + // return 0 = success TORRENT_EXPORT int lazy_bdecode(char const* start, char const* end , lazy_entry& ret, error_code& ec, int* error_pos = 0 @@ -63,7 +67,7 @@ namespace libtorrent , lazy_entry& ret, int depth_limit = 1000, int item_limit = 1000000) TORRENT_DEPRECATED; #endif - struct TORRENT_EXPORT pascal_string + struct pascal_string { pascal_string(char const* p, int l): len(l), ptr(p) {} int len; @@ -156,11 +160,15 @@ namespace libtorrent lazy_entry* dict_find(char const* name); lazy_entry const* dict_find(char const* name) const { return const_cast(this)->dict_find(name); } + lazy_entry* dict_find(std::string const& name); + lazy_entry const* dict_find(std::string const& name) const + { return const_cast(this)->dict_find(name); } std::string dict_find_string_value(char const* name) const; pascal_string dict_find_pstr(char const* name) const; size_type dict_find_int_value(char const* name, size_type default_val = 0) const; lazy_entry const* dict_find_dict(char const* name) const; + lazy_entry const* dict_find_dict(std::string const& name) const; lazy_entry const* dict_find_list(char const* name) const; lazy_entry const* dict_find_string(char const* name) const; lazy_entry const* dict_find_int(char const* name) const; @@ -279,8 +287,12 @@ namespace libtorrent lazy_entry val; }; - TORRENT_EXTRA_EXPORT std::string print_entry(lazy_entry const& e + TORRENT_EXPORT std::string print_entry(lazy_entry const& e , bool single_line = false, int indent = 0); +#if TORRENT_USE_IOSTREAM + TORRENT_EXPORT std::ostream& operator<<(std::ostream& os, lazy_entry const& e); +#endif + } diff --git a/libtorrent/src/error_code.cpp b/libtorrent/src/error_code.cpp index c0950583..accb4c1e 100644 --- a/libtorrent/src/error_code.cpp +++ b/libtorrent/src/error_code.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2008-2012, Arvid Norberg +Copyright (c) 2008, Arvid Norberg All rights reserved. Redistribution and use in source and binary forms, with or without @@ -40,12 +40,12 @@ namespace libtorrent { #if BOOST_VERSION >= 103500 - const char* libtorrent_error_category::name() const throw() + const char* libtorrent_error_category::name() const BOOST_SYSTEM_NOEXCEPT { return "libtorrent error"; } - std::string libtorrent_error_category::message(int ev) const throw() + std::string libtorrent_error_category::message(int ev) const BOOST_SYSTEM_NOEXCEPT { static char const* msgs[] = { @@ -257,30 +257,19 @@ namespace libtorrent "expected value (list, dict, int or string) in bencoded string", "bencoded nesting depth exceeded", "bencoded item count limit exceeded", + "integer overflow", }; if (ev < 0 || ev >= int(sizeof(msgs)/sizeof(msgs[0]))) return "Unknown error"; return msgs[ev]; } - boost::system::error_category& get_libtorrent_category() - { - static libtorrent_error_category libtorrent_category; - return libtorrent_category; - } - - boost::system::error_category& get_http_category() - { - static http_error_category http_category; - return http_category; - } - - const char* http_error_category::name() const throw() + const char* http_error_category::name() const BOOST_SYSTEM_NOEXCEPT { return "http error"; } - std::string http_error_category::message(int ev) const throw() + std::string http_error_category::message(int ev) const BOOST_SYSTEM_NOEXCEPT { std::string ret; ret += to_string(ev).elems; @@ -308,6 +297,19 @@ namespace libtorrent } return ret; } + + boost::system::error_category& get_libtorrent_category() + { + static libtorrent_error_category libtorrent_category; + return libtorrent_category; + } + + boost::system::error_category& get_http_category() + { + static http_error_category http_category; + return http_category; + } + #endif #ifndef BOOST_NO_EXCEPTIONS diff --git a/libtorrent/src/lazy_bdecode.cpp b/libtorrent/src/lazy_bdecode.cpp index 9b1d9950..f85ff629 100644 --- a/libtorrent/src/lazy_bdecode.cpp +++ b/libtorrent/src/lazy_bdecode.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2008-2012, Arvid Norberg +Copyright (c) 2008, Arvid Norberg All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,6 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. */ +#include "libtorrent/config.hpp" #include "libtorrent/lazy_entry.hpp" #include "libtorrent/escape_string.hpp" #include @@ -63,15 +64,33 @@ namespace libtorrent // first occurance of the delimiter is interpreted as an int. // return the pointer to the delimiter, or 0 if there is a // parse error. val should be initialized to zero - char const* parse_int(char const* start, char const* end, char delimiter, boost::int64_t& val) + char const* parse_int(char const* start, char const* end, char delimiter + , boost::int64_t& val, error_code& ec) { while (start < end && *start != delimiter) { - if (!is_digit(*start)) { return 0; } + if (!is_digit(*start)) + { + ec = errors::expected_string; + return start; + } + if (val > INT64_MAX / 10) + { + ec = errors::overflow; + return start; + } val *= 10; - val += *start - '0'; + int digit = *start - '0'; + if (val > INT64_MAX - digit) + { + ec = errors::overflow; + return start; + } + val += digit; ++start; } + if (*start != delimiter) + ec = errors::expected_colon; return start; } @@ -126,9 +145,17 @@ namespace libtorrent } if (!is_digit(t)) TORRENT_FAIL_BDECODE(errors::expected_string); boost::int64_t len = t - '0'; - start = parse_int(start, end, ':', len); - if (start == 0 || start + len + 3 > end || *start != ':') - TORRENT_FAIL_BDECODE(errors::expected_colon); + error_code e; + start = parse_int(start, end, ':', len, e); + if (e) + TORRENT_FAIL_BDECODE(e); + + if (start + len + 1 > end) + TORRENT_FAIL_BDECODE(errors::unexpected_eof); + + if (len < 0) + TORRENT_FAIL_BDECODE(errors::overflow); + ++start; if (start == end) TORRENT_FAIL_BDECODE(errors::unexpected_eof); lazy_entry* ent = top->dict_append(start); @@ -185,9 +212,15 @@ namespace libtorrent TORRENT_FAIL_BDECODE(errors::expected_value); boost::int64_t len = t - '0'; - start = parse_int(start, end, ':', len); - if (start == 0 || start + len + 1 > end || *start != ':') - TORRENT_FAIL_BDECODE(errors::expected_colon); + error_code e; + start = parse_int(start, end, ':', len, e); + if (e) + TORRENT_FAIL_BDECODE(e); + if (start + len + 1 > end) + TORRENT_FAIL_BDECODE(errors::unexpected_eof); + if (len < 0) + TORRENT_FAIL_BDECODE(errors::overflow); + ++start; top->construct_string(start, int(len)); stack.pop_back(); @@ -206,7 +239,10 @@ namespace libtorrent boost::int64_t val = 0; bool negative = false; if (*m_data.start == '-') negative = true; - parse_int(negative?m_data.start+1:m_data.start, m_data.start + m_size, 'e', val); + error_code ec; + parse_int(m_data.start + negative + , m_data.start + m_size, 'e', val, ec); + if (ec) return 0; if (negative) val = -val; return val; } @@ -339,6 +375,13 @@ namespace libtorrent return e; } + lazy_entry const* lazy_entry::dict_find_dict(std::string const& name) const + { + lazy_entry const* e = dict_find(name); + if (e == 0 || e->type() != lazy_entry::dict_t) return 0; + return e; + } + lazy_entry const* lazy_entry::dict_find_list(char const* name) const { lazy_entry const* e = dict_find(name); @@ -358,6 +401,20 @@ namespace libtorrent return 0; } + lazy_entry* lazy_entry::dict_find(std::string const& name) + { + TORRENT_ASSERT(m_type == dict_t); + for (int i = 0; i < int(m_size); ++i) + { + lazy_dict_entry& e = m_data.dict[i]; + if (name.size() != e.val.m_begin - e.name) continue; + if (std::equal(name.begin(), name.end(), e.name)) + return &e.val; + } + return 0; + } + + lazy_entry* lazy_entry::list_append() { TORRENT_ASSERT(m_type == list_t); @@ -426,6 +483,13 @@ namespace libtorrent return return_t(m_begin, m_len); } +#if TORRENT_USE_IOSTREAM + std::ostream& operator<<(std::ostream& os, lazy_entry const& e) + { + return os << print_entry(e); + } +#endif // TORRENT_USE_IOSTREAM + int line_longer_than(lazy_entry const& e, int limit) { int line_len = 0; @@ -491,7 +555,7 @@ namespace libtorrent case lazy_entry::int_t: { char str[100]; - snprintf(str, sizeof(str), "%"PRId64, e.int_value()); + snprintf(str, sizeof(str), "%" PRId64, e.int_value()); return str; } case lazy_entry::string_t: