improve error reporting of lazy_bdecode to use error_code

This commit is contained in:
Arvid Norberg 2010-10-28 04:01:59 +00:00
parent d737dd051d
commit fc1b44b560
19 changed files with 135 additions and 73 deletions

View File

@ -842,7 +842,8 @@ int main(int argc, char* argv[])
if (load_file(".ses_state", in) == 0)
{
lazy_entry e;
if (lazy_bdecode(&in[0], &in[0] + in.size(), e) == 0)
error_code ec;
if (lazy_bdecode(&in[0], &in[0] + in.size(), e, ec) == 0)
ses.load_state(e);
}

View File

@ -60,17 +60,18 @@ int main(int argc, char* argv[])
return 1;
}
lazy_entry e;
ret = lazy_bdecode(&buf[0], &buf[0] + buf.size(), e);
error_code ec;
int pos;
ret = lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec, &pos);
if (ret != 0)
{
fprintf(stderr, "invalid bencoding: %d\n", ret);
fprintf(stderr, "failed to decode: '%s' at character: %d\n", ec.message().c_str(), pos);
return 1;
}
printf("\n\n----- raw info -----\n\n%s\n", print_entry(e).c_str());
error_code ec;
torrent_info t(e, ec);
if (ec)
{

View File

@ -245,6 +245,23 @@ namespace libtorrent
invalid_tracker_response_length,
invalid_tracker_transaction_id,
invalid_tracker_action,
reserved180,
reserved181,
reserved182,
reserved183,
reserved184,
reserved185,
reserved186,
reserved187,
reserved188,
reserved189,
// bdecode errors
expected_string, // 190
expected_colon,
unexpected_eof,
expected_value,
depth_exceeded,
error_code_max
};

View File

@ -40,6 +40,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/size_type.hpp"
#include "libtorrent/error_code.hpp"
#if TORRENT_USE_IOSTREAM
#include <iosfwd>
@ -52,7 +53,9 @@ namespace libtorrent
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, int depth_limit = 1000);
TORRENT_EXPORT int lazy_bdecode(char const* start, char const* end
, lazy_entry& ret, error_code& ec, int* error_pos = 0
, int depth_limit = 1000);
struct pascal_string
{

View File

@ -374,8 +374,11 @@ namespace libtorrent
lazy_entry const* info(char const* key) const
{
if (m_info_dict.type() == lazy_entry::none_t)
{
error_code ec;
lazy_bdecode(m_info_section.get(), m_info_section.get()
+ m_info_section_size, m_info_dict);
+ m_info_section_size, m_info_dict, ec);
}
return m_info_dict.dict_find(key);
}

View File

@ -1248,7 +1248,9 @@ namespace libtorrent
(*m_logger) << time_now_string() << " <== HASHPIECE " << p.piece << " list: " << list_size << " ";
#endif
lazy_entry hash_list;
if (lazy_bdecode(recv_buffer.begin + 13, recv_buffer.end + 13 + list_size, hash_list) != 0)
error_code ec;
if (lazy_bdecode(recv_buffer.begin + 13, recv_buffer.end + 13 + list_size
, hash_list, ec) != 0)
{
disconnect(errors::invalid_hash_piece, 2);
return;
@ -1518,11 +1520,14 @@ namespace libtorrent
buffer::const_interval recv_buffer = receive_buffer();
lazy_entry root;
lazy_bdecode(recv_buffer.begin + 2, recv_buffer.end, root);
error_code ec;
int pos;
lazy_bdecode(recv_buffer.begin + 2, recv_buffer.end, root, ec, &pos);
if (root.type() != lazy_entry::dict_t)
{
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string() << " invalid extended handshake\n";
(*m_logger) << time_now_string() << " invalid extended handshake: " << ec.message()
<< "pos: " << pos << "\n";
#endif
return;
}

View File

@ -233,6 +233,23 @@ namespace libtorrent
"udp tracker response packet has invalid size",
"invalid transaction id in udp tracker response",
"invalid action field in udp tracker response",
"",
"",
"",
"",
"",
"",
"",
"",
"",
// bdecode errors
"expected string in bdecoded string",
"expected colon in bdecoded string",
"unexpected end of file in bdecoded string",
"expected value (list, dict, int or string) in bencoded string",
"bencoded nesting depth exceeded",
};
if (ev < 0 || ev >= sizeof(msgs)/sizeof(msgs[0]))
return "Unknown error";

View File

@ -301,7 +301,8 @@ namespace libtorrent
// handle tracker response
lazy_entry e;
int res = lazy_bdecode(data, data + size, e);
error_code ecode;
int res = lazy_bdecode(data, data + size, e, ecode);
if (res == 0 && e.type() == lazy_entry::dict_t)
{
@ -309,7 +310,7 @@ namespace libtorrent
}
else
{
fail(error_code(errors::invalid_bencoding), parser.status_code());
fail(ecode, parser.status_code());
}
close();
}

View File

@ -509,11 +509,14 @@ namespace libtorrent { namespace dht
TORRENT_ASSERT(bytes_transferred > 0);
lazy_entry e;
int ret = lazy_bdecode(buf, buf + bytes_transferred, e);
int pos;
error_code ec;
int ret = lazy_bdecode(buf, buf + bytes_transferred, e, ec, &pos);
if (ret != 0)
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(dht_tracker) << "<== " << ep << " ERROR: Invalid bencoding";
TORRENT_LOG(dht_tracker) << "<== " << ep << " ERROR: "
<< ec.message() << " pos: " << pos;
#endif
return;
}
@ -615,16 +618,16 @@ namespace libtorrent { namespace dht
m_send_buf.clear();
bencode(std::back_inserter(m_send_buf), e);
error_code ec;
#ifdef TORRENT_DHT_VERBOSE_LOGGING
std::stringstream log_line;
lazy_entry print;
int ret = lazy_bdecode(&m_send_buf[0], &m_send_buf[0] + m_send_buf.size(), print);
int ret = lazy_bdecode(&m_send_buf[0], &m_send_buf[0] + m_send_buf.size(), print, 0, ec);
TORRENT_ASSERT(ret == 0);
log_line << print_entry(print, true);
#endif
error_code ec;
if (m_sock.send(addr, &m_send_buf[0], (int)m_send_buf.size(), ec, send_flags))
{
if (ec) return false;

View File

@ -47,12 +47,14 @@ namespace
namespace libtorrent
{
int fail_bdecode(lazy_entry& ret, int return_value = -1)
{
ret.clear();
return return_value;
}
#define TORRENT_FAIL_BDECODE(code) \
{ \
ec = code; \
if (error_pos) *error_pos = start - orig_start; \
ret.clear(); \
return -1; \
}
// fills in 'val' with what the string between start and the
// first occurance of the delimiter is interpreted as an int.
// return the pointer to the delimiter, or 0 if there is a
@ -76,8 +78,10 @@ namespace libtorrent
}
// return 0 = success
int lazy_bdecode(char const* start, char const* end, lazy_entry& ret, int depth_limit)
int lazy_bdecode(char const* start, char const* end, lazy_entry& ret
, error_code& ec, int* error_pos, int depth_limit)
{
char const* const orig_start = start;
ret.clear();
if (start == end) return 0;
@ -90,11 +94,11 @@ namespace libtorrent
lazy_entry* top = stack.back();
if (int(stack.size()) > depth_limit) return fail_bdecode(ret);
if (start >= end) return fail_bdecode(ret);
if (int(stack.size()) > depth_limit) TORRENT_FAIL_BDECODE(errors::depth_exceeded);
if (start >= end) TORRENT_FAIL_BDECODE(errors::unexpected_eof);
char t = *start;
++start;
if (start >= end && t != 'e') return fail_bdecode(ret);
if (start >= end && t != 'e') TORRENT_FAIL_BDECODE(errors::unexpected_eof);
switch (top->type())
{
@ -106,16 +110,17 @@ namespace libtorrent
stack.pop_back();
continue;
}
if (!is_digit(t)) return fail_bdecode(ret);
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 != ':') return fail_bdecode(ret);
if (start == 0 || start + len + 3 > end || *start != ':')
TORRENT_FAIL_BDECODE(errors::expected_colon);
++start;
if (start == end) return fail_bdecode(ret);
if (start == end) TORRENT_FAIL_BDECODE(errors::unexpected_eof);
lazy_entry* ent = top->dict_append(start);
if (ent == 0) return fail_bdecode(ret, -2);
if (ent == 0) TORRENT_FAIL_BDECODE(errors::no_memory);
start += len;
if (start >= end) return fail_bdecode(ret);
if (start >= end) TORRENT_FAIL_BDECODE(errors::unexpected_eof);
stack.push_back(ent);
t = *start;
++start;
@ -130,7 +135,7 @@ namespace libtorrent
continue;
}
lazy_entry* ent = top->list_append();
if (ent == 0) return fail_bdecode(ret, -2);
if (ent == 0) TORRENT_FAIL_BDECODE(errors::no_memory);
stack.push_back(ent);
break;
}
@ -151,7 +156,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) return fail_bdecode(ret);
if (start == end) TORRENT_FAIL_BDECODE(errors::unexpected_eof);
TORRENT_ASSERT(*start == 'e');
++start;
stack.pop_back();
@ -159,11 +164,12 @@ namespace libtorrent
}
default:
{
if (!is_digit(t)) return fail_bdecode(ret);
if (!is_digit(t)) 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 != ':') return fail_bdecode(ret);
if (start == 0 || start + len + 1 > end || *start != ':')
TORRENT_FAIL_BDECODE(errors::expected_colon);
++start;
top->construct_string(start, int(len));
stack.pop_back();

View File

@ -191,7 +191,8 @@ namespace libtorrent { namespace
if (!m_pc.packet_finished()) return true;
lazy_entry msg;
int ret = lazy_bdecode(body.begin, body.end, msg);
error_code ec;
int ret = lazy_bdecode(body.begin, body.end, msg, ec);
if (ret != 0 || msg.type() != lazy_entry::dict_t)
{
m_pc.disconnect(errors::invalid_lt_tracker_message, 2);

View File

@ -407,7 +407,8 @@ namespace libtorrent
std::vector<char> buf;
bencode(std::back_inserter(buf), ses_state);
lazy_entry e;
lazy_bdecode(&buf[0], &buf[0] + buf.size(), e);
error_code ec;
lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec);
TORRENT_SYNC_CALL1(load_state, &e);
}

View File

@ -445,18 +445,20 @@ namespace libtorrent
if (!m_resume_data.empty())
{
int pos;
error_code ec;
if (lazy_bdecode(&m_resume_data[0], &m_resume_data[0]
+ m_resume_data.size(), m_resume_entry) != 0)
+ m_resume_data.size(), m_resume_entry, ec, &pos) != 0)
{
std::vector<char>().swap(m_resume_data);
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
(*m_ses.m_logger) << time_now_string() << " fastresume data for "
<< torrent_file().name() << " rejected: " << ec.message()
<< " pos: " << pos << "\n";
#endif
if (m_ses.m_alerts.should_post<fastresume_rejected_alert>())
{
error_code ec(errors::parse_failed);
m_ses.m_alerts.post_alert(fastresume_rejected_alert(get_handle(), ec));
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
(*m_ses.m_logger) << time_now_string() << " fastresume data for "
<< torrent_file().name() << " rejected: " << ec.message() << "\n";
#endif
}
}
}
@ -4474,8 +4476,8 @@ namespace libtorrent
}
lazy_entry metadata;
int ret = lazy_bdecode(metadata_buf, metadata_buf + metadata_size, metadata);
error_code ec;
int ret = lazy_bdecode(metadata_buf, metadata_buf + metadata_size, metadata, ec);
if (ret != 0 || !m_torrent_file->parse_info_section(metadata, ec))
{
// this means the metadata is correct, since we
@ -4483,6 +4485,7 @@ namespace libtorrent
// failed to parse it. Pause the torrent
if (alerts().should_post<metadata_failed_alert>())
{
// TODO: pass in ec along with the alert
alerts().post_alert(metadata_failed_alert(get_handle()));
}
set_error(errors::invalid_swarm_metadata, "");

View File

@ -456,10 +456,11 @@ namespace libtorrent
{
if (m_info_section_size > 0)
{
error_code ec;
m_info_section.reset(new char[m_info_section_size]);
memcpy(m_info_section.get(), t.m_info_section.get(), m_info_section_size);
int ret = lazy_bdecode(m_info_section.get(), m_info_section.get()
+ m_info_section_size, m_info_dict);
+ m_info_section_size, m_info_dict, ec);
lazy_entry const* pieces = m_info_dict.dict_find_string("pieces");
if (pieces && pieces->string_length() == m_files.num_pieces() * 20)
@ -498,14 +499,14 @@ namespace libtorrent
bencode(out, torrent_file);
lazy_entry e;
if (lazy_bdecode(&tmp[0], &tmp[0] + tmp.size(), e) != 0)
error_code ec;
if (lazy_bdecode(&tmp[0], &tmp[0] + tmp.size(), e, ec) != 0)
{
#ifndef BOOST_NO_EXCEPTIONS
throw invalid_torrent_file(errors::invalid_bencoding);
#endif
return;
}
error_code ec;
#ifndef BOOST_NO_EXCEPTIONS
if (!parse_torrent_file(e, ec))
throw invalid_torrent_file(ec);
@ -541,8 +542,8 @@ namespace libtorrent
{
error_code ec;
lazy_entry e;
if (lazy_bdecode(buffer, buffer + size, e) != 0)
throw invalid_torrent_file(errors::invalid_bencoding);
if (lazy_bdecode(buffer, buffer + size, e, ec) != 0)
throw invalid_torrent_file(ec);
if (!parse_torrent_file(e, ec))
throw invalid_torrent_file(ec);
@ -561,9 +562,10 @@ namespace libtorrent
if (ret < 0) return;
lazy_entry e;
if (lazy_bdecode(&buf[0], &buf[0] + buf.size(), e) != 0)
throw invalid_torrent_file(errors::invalid_bencoding);
error_code ec;
if (lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec) != 0)
throw invalid_torrent_file(ec);
if (!parse_torrent_file(e, ec))
throw invalid_torrent_file(ec);
}
@ -585,10 +587,10 @@ namespace libtorrent
if (ret < 0) return;
lazy_entry e;
if (lazy_bdecode(&buf[0], &buf[0] + buf.size(), e) != 0)
throw invalid_torrent_file(errors::invalid_bencoding);
error_code ec;
if (lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec) != 0)
throw invalid_torrent_file(ec);
if (!parse_torrent_file(e, ec))
throw invalid_torrent_file(ec);
}
@ -616,11 +618,8 @@ namespace libtorrent
, m_i2p(false)
{
lazy_entry e;
if (lazy_bdecode(buffer, buffer + size, e) != 0)
{
ec = errors::invalid_bencoding;
if (lazy_bdecode(buffer, buffer + size, e, ec) != 0)
return;
}
parse_torrent_file(e, ec);
}
@ -637,11 +636,8 @@ namespace libtorrent
if (ret < 0) return;
lazy_entry e;
if (lazy_bdecode(&buf[0], &buf[0] + buf.size(), e) != 0)
{
ec = errors::invalid_bencoding;
if (lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec) != 0)
return;
}
parse_torrent_file(e, ec);
}
@ -661,11 +657,8 @@ namespace libtorrent
if (ret < 0) return;
lazy_entry e;
if (lazy_bdecode(&buf[0], &buf[0] + buf.size(), e) != 0)
{
ec = errors::invalid_bencoding;
if (lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec) != 0)
return;
}
parse_torrent_file(e, ec);
}
#endif

View File

@ -243,7 +243,8 @@ namespace libtorrent { namespace
if (body.left() < length) return true;
lazy_entry pex_msg;
int ret = lazy_bdecode(body.begin, body.end, pex_msg);
error_code ec;
int ret = lazy_bdecode(body.begin, body.end, pex_msg, ec);
if (ret != 0 || pex_msg.type() != lazy_entry::dict_t)
{
m_pc.disconnect(errors::invalid_pex_message, 2);

View File

@ -17,7 +17,8 @@ int test_main()
{
char b[] = "d1:ai12453e1:b3:aaa1:c3:bbbe";
lazy_entry e;
int ret = lazy_bdecode(b, b + sizeof(b)-1, e);
error_code ec;
int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
}
ptime stop(time_now());

View File

@ -107,7 +107,8 @@ int test_main()
{
char b[] = "i12453e";
lazy_entry e;
int ret = lazy_bdecode(b, b + sizeof(b)-1, e);
error_code ec;
int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
TORRENT_ASSERT(ret == 0);
#if TORRENT_USE_IOSTREAM
std::cout << e << std::endl;
@ -122,7 +123,8 @@ int test_main()
{
char b[] = "26:abcdefghijklmnopqrstuvwxyz";
lazy_entry e;
int ret = lazy_bdecode(b, b + sizeof(b)-1, e);
error_code ec;
int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
TORRENT_ASSERT(ret == 0);
#if TORRENT_USE_IOSTREAM
std::cout << e << std::endl;
@ -138,7 +140,8 @@ int test_main()
{
char b[] = "li12453e3:aaae";
lazy_entry e;
int ret = lazy_bdecode(b, b + sizeof(b)-1, e);
error_code ec;
int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
TORRENT_ASSERT(ret == 0);
#if TORRENT_USE_IOSTREAM
std::cout << e << std::endl;
@ -161,7 +164,8 @@ int test_main()
{
char b[] = "d1:ai12453e1:b3:aaa1:c3:bbb1:X10:0123456789e";
lazy_entry e;
int ret = lazy_bdecode(b, b + sizeof(b)-1, e);
error_code ec;
int ret = lazy_bdecode(b, b + sizeof(b)-1, e, ec);
TORRENT_ASSERT(ret == 0);
#if TORRENT_USE_IOSTREAM
std::cout << e << std::endl;
@ -201,7 +205,8 @@ int test_main()
printf("%s\n", buf);
lazy_entry e;
int ret = lazy_bdecode(buf, buf + sizeof(buf), e);
error_code ec;
int ret = lazy_bdecode(buf, buf + sizeof(buf), e, ec);
TEST_CHECK(ret == -1);
}
return 0;

View File

@ -66,7 +66,7 @@ void send_dht_msg(datagram_socket& sock, char const* msg, lazy_entry* reply, cha
TEST_CHECK(!ec);
if (ec) std::cout << ec.message() << std::endl;
int ret = lazy_bdecode(inbuf, inbuf + size, *reply);
int ret = lazy_bdecode(inbuf, inbuf + size, *reply, ec);
TEST_CHECK(ret == 0);
}

View File

@ -462,7 +462,7 @@ int test_main()
std::vector<char> buf;
bencode(std::back_inserter(buf), session_state);
lazy_entry session_state2;
ret = lazy_bdecode(&buf[0], &buf[0] + buf.size(), session_state2);
ret = lazy_bdecode(&buf[0], &buf[0] + buf.size(), session_state2, ec);
TEST_CHECK(ret == 0);
fprintf(stderr, "session_state\n%s\n", print_entry(session_state2).c_str());