add piece index range checks on have_piece() and read_piece()

This commit is contained in:
arvidn 2018-07-23 08:43:56 +02:00 committed by Arvid Norberg
parent 27836ede70
commit a1f2995716
4 changed files with 98 additions and 4 deletions

View File

@ -777,6 +777,15 @@ namespace libtorrent {
return m_picker->have_piece(index);
}
// returns true if we have downloaded the given piece
bool user_have_piece(piece_index_t index) const
{
if (!valid_metadata()) return false;
if (index < piece_index_t{0} || index >= m_torrent_file->end_piece()) return false;
if (!has_picker()) return m_have_all;
return m_picker->have_piece(index);
}
// returns true if we have downloaded the given piece
bool has_piece_passed(piece_index_t index) const
{

View File

@ -830,11 +830,23 @@ bool is_downloading_state(int const st)
void torrent::read_piece(piece_index_t const piece)
{
error_code ec;
if (m_abort || m_deleted)
{
// failed
m_ses.alerts().emplace_alert<read_piece_alert>(
get_handle(), piece, error_code(boost::system::errc::operation_canceled, generic_category()));
ec.assign(boost::system::errc::operation_canceled, generic_category());
}
else if (!valid_metadata())
{
ec.assign(errors::no_metadata, libtorrent_category());
}
else if (piece < piece_index_t{0} || piece >= m_torrent_file->end_piece())
{
ec.assign(errors::invalid_piece_index, libtorrent_category());
}
if (ec)
{
m_ses.alerts().emplace_alert<read_piece_alert>(get_handle(), piece, ec);
return;
}

View File

@ -664,7 +664,7 @@ namespace libtorrent {
bool torrent_handle::have_piece(piece_index_t piece) const
{
return sync_call_ret<bool>(false, &torrent::have_piece, piece);
return sync_call_ret<bool>(false, &torrent::user_have_piece, piece);
}
storage_interface* torrent_handle::get_storage_impl() const

View File

@ -618,3 +618,76 @@ TORRENT_TEST(test_move_storage_no_metadata)
TEST_EQUAL(h.status().save_path, complete("save_path_1"));
}
TORRENT_TEST(test_have_piece_no_metadata)
{
lt::session ses(settings());
error_code ec;
add_torrent_params p = parse_magnet_uri("magnet?xt=urn:btih:abababababababababababababababababababab", ec);
p.save_path = "save_path";
torrent_handle h = ses.add_torrent(p);
TEST_EQUAL(h.have_piece(piece_index_t{-1}), false);
TEST_EQUAL(h.have_piece(piece_index_t{0}), false);
TEST_EQUAL(h.have_piece(piece_index_t{100}), false);
}
TORRENT_TEST(test_have_piece_out_of_range)
{
lt::session ses(settings());
error_code ec;
add_torrent_params p;
static std::array<const int, 2> const file_sizes{{100000, 100000}};
int const piece_size = 0x8000;
p.ti = make_torrent(file_sizes, piece_size);
p.save_path = "save_path";
p.flags |= torrent_flags::seed_mode;
torrent_handle h = ses.add_torrent(p);
TEST_EQUAL(h.have_piece(piece_index_t{-1}), false);
TEST_EQUAL(h.have_piece(piece_index_t{0}), true);
TEST_EQUAL(h.have_piece(piece_index_t{100}), false);
}
TORRENT_TEST(test_read_piece_no_metadata)
{
lt::session ses(settings());
error_code ec;
add_torrent_params p = parse_magnet_uri("magnet?xt=urn:btih:abababababababababababababababababababab", ec);
p.save_path = "save_path";
torrent_handle h = ses.add_torrent(p);
h.read_piece(piece_index_t{-1});
alert const* a = wait_for_alert(ses, read_piece_alert::alert_type, "read_piece_alert");
TEST_CHECK(a);
if (auto* rp = alert_cast<read_piece_alert>(a))
{
TEST_CHECK(rp->error == error_code(lt::errors::no_metadata, lt::libtorrent_category()));
}
}
TORRENT_TEST(test_read_piece_out_of_range)
{
lt::session ses(settings());
error_code ec;
add_torrent_params p;
static std::array<const int, 2> const file_sizes{{100000, 100000}};
int const piece_size = 0x8000;
p.ti = make_torrent(file_sizes, piece_size);
p.save_path = "save_path";
p.flags |= torrent_flags::seed_mode;
torrent_handle h = ses.add_torrent(p);
h.read_piece(piece_index_t{-1});
alert const* a = wait_for_alert(ses, read_piece_alert::alert_type, "read_piece_alert");
TEST_CHECK(a);
if (auto* rp = alert_cast<read_piece_alert>(a))
{
TEST_CHECK(rp->error == error_code(lt::errors::invalid_piece_index
, lt::libtorrent_category()));
}
}