break out bdecode errors into its own category

This commit is contained in:
Arvid Norberg 2013-10-22 23:57:12 +00:00
parent 4e94ae592c
commit 0158710f5c
4 changed files with 97 additions and 24 deletions

View File

@ -416,7 +416,7 @@ namespace libtorrent
// invalid action field in udp tracker response
invalid_tracker_action,
#ifndef TORRENT_NO_DEPRECATE
// expected string in bencoded string
expected_string = 190,
// expected colon in bencoded string
@ -429,6 +429,7 @@ namespace libtorrent
depth_exceeded,
// bencoded item count limit exceeded
limit_exceeded,
#endif
// the number of error codes
error_code_max
@ -498,14 +499,6 @@ namespace libtorrent
#else
struct TORRENT_EXPORT libtorrent_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); }
};
struct TORRENT_EXPORT http_error_category : boost::system::error_category
{
virtual const char* name() const BOOST_SYSTEM_NOEXCEPT;

View File

@ -367,8 +367,41 @@ namespace libtorrent
TORRENT_EXTRA_EXPORT std::string print_entry(lazy_entry const& e
, bool single_line = false, int indent = 0);
}
TORRENT_EXPORT boost::system::error_category& get_bdecode_category();
namespace bdecode_errors
{
// libtorrent uses boost.system's ``error_code`` class to represent errors. libtorrent has
// its own error category get_bdecode_category() whith the error codes defined by error_code_enum.
enum error_code_enum
{
// Not an error
no_error = 0,
// expected string in bencoded string
expected_string,
// expected colon in bencoded string
expected_colon,
// unexpected end of file in bencoded string
unexpected_eof,
// expected value (list, dict, int or string) in bencoded string
expected_value,
// bencoded recursion depth limit exceeded
depth_exceeded,
// bencoded item count limit exceeded
limit_exceeded,
// the number of error codes
error_code_max
};
// hidden
inline boost::system::error_code make_error_code(error_code_enum e)
{
return boost::system::error_code(e, get_bdecode_category());
}
}
}
#endif

View File

@ -40,6 +40,14 @@ namespace libtorrent
{
#if BOOST_VERSION >= 103500
struct libtorrent_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); }
};
const char* libtorrent_error_category::name() const BOOST_SYSTEM_NOEXCEPT
{
return "libtorrent error";
@ -239,6 +247,7 @@ namespace libtorrent
"udp tracker response packet has invalid size",
"invalid transaction id in udp tracker response",
"invalid action field in udp tracker response",
#ifndef TORRENT_NO_DEPRECATE
"",
"",
"",
@ -257,6 +266,7 @@ namespace libtorrent
"expected value (list, dict, int or string) in bencoded string",
"bencoded nesting depth exceeded",
"bencoded item count limit exceeded",
#endif
};
if (ev < 0 || ev >= int(sizeof(msgs)/sizeof(msgs[0])))
return "Unknown error";

View File

@ -45,7 +45,7 @@ namespace libtorrent
#define TORRENT_FAIL_BDECODE(code) \
{ \
ec = code; \
ec = make_error_code(code); \
while (!stack.empty()) { \
top = stack.back(); \
if (top->type() == lazy_entry::dict_t || top->type() == lazy_entry::list_t) top->pop(); \
@ -103,11 +103,11 @@ namespace libtorrent
lazy_entry* top = stack.back();
if (int(stack.size()) > depth_limit) TORRENT_FAIL_BDECODE(errors::depth_exceeded);
if (start >= end) TORRENT_FAIL_BDECODE(errors::unexpected_eof);
if (int(stack.size()) > depth_limit) TORRENT_FAIL_BDECODE(bdecode_errors::depth_exceeded);
if (start >= end) TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof);
char t = *start;
++start;
if (start >= end && t != 'e') TORRENT_FAIL_BDECODE(errors::unexpected_eof);
if (start >= end && t != 'e') TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof);
switch (top->type())
{
@ -119,17 +119,17 @@ namespace libtorrent
stack.pop_back();
continue;
}
if (!is_digit(t)) TORRENT_FAIL_BDECODE(errors::expected_string);
if (!is_digit(t)) TORRENT_FAIL_BDECODE(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);
TORRENT_FAIL_BDECODE(bdecode_errors::expected_colon);
++start;
if (start == end) TORRENT_FAIL_BDECODE(errors::unexpected_eof);
if (start == end) TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof);
lazy_entry* ent = top->dict_append(start);
if (ent == 0) TORRENT_FAIL_BDECODE(errors::no_memory);
if (ent == 0) TORRENT_FAIL_BDECODE(boost::system::errc::not_enough_memory);
start += len;
if (start >= end) TORRENT_FAIL_BDECODE(errors::unexpected_eof);
if (start >= end) TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof);
stack.push_back(ent);
t = *start;
++start;
@ -144,7 +144,7 @@ namespace libtorrent
continue;
}
lazy_entry* ent = top->list_append();
if (ent == 0) TORRENT_FAIL_BDECODE(errors::no_memory);
if (ent == 0) TORRENT_FAIL_BDECODE(boost::system::errc::not_enough_memory);
stack.push_back(ent);
break;
}
@ -152,7 +152,7 @@ namespace libtorrent
}
--item_limit;
if (item_limit <= 0) TORRENT_FAIL_BDECODE(errors::limit_exceeded);
if (item_limit <= 0) TORRENT_FAIL_BDECODE(bdecode_errors::limit_exceeded);
top = stack.back();
switch (t)
@ -168,7 +168,7 @@ namespace libtorrent
char const* int_start = start;
start = find_char(start, end, 'e');
top->construct_int(int_start, start - int_start);
if (start == end) TORRENT_FAIL_BDECODE(errors::unexpected_eof);
if (start == end) TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof);
TORRENT_ASSERT(*start == 'e');
++start;
stack.pop_back();
@ -177,12 +177,12 @@ namespace libtorrent
default:
{
if (!is_digit(t))
TORRENT_FAIL_BDECODE(errors::expected_value);
TORRENT_FAIL_BDECODE(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);
TORRENT_FAIL_BDECODE(bdecode_errors::expected_colon);
++start;
top->construct_string(start, int(len));
stack.pop_back();
@ -555,5 +555,42 @@ namespace libtorrent
}
return ret;
}
struct bdecode_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); }
};
const char* bdecode_error_category::name() const BOOST_SYSTEM_NOEXCEPT
{
return "bdecode error";
}
std::string bdecode_error_category::message(int ev) const BOOST_SYSTEM_NOEXCEPT
{
static char const* msgs[] =
{
"no error",
"expected string in bencoded string",
"expected colon in bencoded string",
"unexpected end of file in bencoded string",
"expected value (list, dict, int or string) in bencoded string",
"bencoded nesting depth exceeded",
"bencoded item count limit exceeded",
};
if (ev < 0 || ev >= int(sizeof(msgs)/sizeof(msgs[0])))
return "Unknown error";
return msgs[ev];
}
boost::system::error_category& get_bdecode_category()
{
static bdecode_error_category bdecode_category;
return bdecode_category;
}
};