Skip to content

Commit

Permalink
merged RC_2_0 into master
Browse files Browse the repository at this point in the history
  • Loading branch information
arvidn committed Nov 15, 2023
2 parents 8e53eba + 3a6b331 commit 5f5f8e0
Show file tree
Hide file tree
Showing 13 changed files with 77 additions and 25 deletions.
15 changes: 13 additions & 2 deletions .github/workflows/macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,18 @@ jobs:

- name: install boost
run: |
brew install boost-build boost
git clone --depth=1 --recurse-submodules -j10 --branch=boost-1.78.0 https://github.com/boostorg/boost.git
cd boost
./bootstrap.sh
- name: boost headers
run: |
cd boost
./b2 headers
cp b2 ..
- name: user-config
run: |
echo "using darwin : ios_sim : clang++ : <compileflags>-Wno-deprecated-declarations
<compileflags>\"-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk\"
<compileflags>-mios-simulator-version-min=12
Expand All @@ -146,4 +157,4 @@ jobs:
- name: build library
run: |
b2 -l400 address-model=64 darwin-ios darwin-ios_sim link=static
BOOST_ROOT=boost ./b2 -l400 cxxstd=14 target-os=iphone crypto=built-in darwin-ios darwin-ios_sim address-model=64 link=static
8 changes: 8 additions & 0 deletions Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,14 @@ rule linking ( properties * )
result += <framework>CoreFoundation <framework>SystemConfiguration ;
}

if <target-os>iphone in $(properties)
{
# boost.asio seems to mis-detect iOS as supporting the __thread
# keyword, resulting in the error:
# error: thread-local storage is not supported for the current target
result += <define>BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION ;
}

if <toolset>gcc in $(properties)
&& <target-os>linux in $(properties)
&& ( <asserts>on in $(properties)
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -1045,6 +1045,7 @@ TEST_TORRENTS = \
invalid_pieces.torrent \
invalid_symlink.torrent \
large.torrent \
large_piece_size.torrent \
long_name.torrent \
many_pieces.torrent \
missing_path_list.torrent \
Expand Down
1 change: 1 addition & 0 deletions bindings/python/src/session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1182,6 +1182,7 @@ void bind_session()
.def("post_session_stats", allow_threads(&lt::session::post_session_stats))
.def("is_listening", allow_threads(&lt::session::is_listening))
.def("listen_port", allow_threads(&lt::session::listen_port))
.def("ssl_listen_port", allow_threads(&lt::session::ssl_listen_port))
#ifndef TORRENT_DISABLE_DHT
.def("add_dht_node", &add_dht_node)
#if TORRENT_ABI_VERSION == 1
Expand Down
1 change: 1 addition & 0 deletions bindings/python/src/torrent_handle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,7 @@ void bind_torrent_handle()
.def("force_recheck", _(&torrent_handle::force_recheck))
.def("rename_file", &rename_file0)
.def("rename_file", &rename_file1)
.def("set_ssl_certificate_buffer", &torrent_handle::set_ssl_certificate_buffer, (arg("cert"), arg("private_key"), arg("dh_params")))
.def("set_ssl_certificate", &torrent_handle::set_ssl_certificate, (arg("cert"), arg("private_key"), arg("dh_params"), arg("passphrase")=""))
.def("flags", _(&torrent_handle::flags))
.def("set_flags", _(set_flags0))
Expand Down
13 changes: 10 additions & 3 deletions include/libtorrent/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -589,10 +589,17 @@ see LICENSE file.
#define __has_builtin(x) 0 // for non-clang compilers
#endif

#if __cplusplus >= 202002L
#define TORRENT_RVO(x) x
#if defined __clang__
// for some reason, clang warns on relying on guaranteed copy elision,
// suggesting an explicit call to std::move() instead
// local variable 'X' will be copied despite being returned by name
// call 'std::move' explicitly to avoid copying
# define TORRENT_RVO(x) std::move(x)
#elif (__cplusplus >= 201703L && defined __cpp_guaranteed_copy_elision) \
|| (defined _MSC_VER && _MSC_VER > 1928)
# define TORRENT_RVO(x) x
#else
#define TORRENT_RVO(x) std::move(x)
# define TORRENT_RVO(x) std::move(x)
#endif

#if (TORRENT_HAS_SSE && defined __GNUC__)
Expand Down
15 changes: 15 additions & 0 deletions include/libtorrent/file_storage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,21 @@ TORRENT_VERSION_NAMESPACE_4
, std::int64_t((std::numeric_limits<int>::max)() / 2) * default_block_size);
static constexpr std::int64_t max_file_offset = (std::int64_t(1) << 48) - 1;

// we use a signed 32 bit integer for piece indices internally, but
// frequently need headroom for intermediate calculations, so we limit
// the number of pieces 1 bit below the maximum
static constexpr std::int32_t max_num_pieces = (std::int32_t(1) << 30) - 1;

// limit the piece length at (2 ^ 30) to get a bit of headroom. We
// commonly compute the number of blocks per pieces by adding
// block_size - 1 before dividing by block_size. That would overflow with
// a piece size of 2 ^ 31. This limit is still an unreasonably large
// piece size anyway.
// The piece picker (currently) has a limit of no more than (2^15)-1
// blocks per piece, which is more restrictive, at a block size of 16
// kiB (0x4000).
static constexpr std::int32_t max_piece_size = ((1 << 15) - 1) * 0x4000;

// returns true if the piece length has been initialized
// on the file_storage. This is typically taken as a proxy
// of whether the file_storage as a whole is initialized or
Expand Down
4 changes: 4 additions & 0 deletions include/libtorrent/web_seed_entry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ see LICENSE file.
#ifndef TORRENT_WEB_SEED_ENTRY_HPP_INCLUDED
#define TORRENT_WEB_SEED_ENTRY_HPP_INCLUDED

#if TORRENT_ABI_VERSION < 4
#include <cstdint>
#endif

#include <vector>
#include <string>
#include "libtorrent/config.hpp"
Expand Down
12 changes: 3 additions & 9 deletions src/torrent_info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ namespace {
// calculations of the size of the merkle tree (which is all 'int'
// indices)
if (file_size < 0
|| (file_size / default_block_size) >= std::numeric_limits<int>::max() / 2
|| (file_size / default_block_size) >= file_storage::max_num_pieces
|| file_size > file_storage::max_file_size)
{
ec = errors::torrent_invalid_length;
Expand Down Expand Up @@ -1128,12 +1128,7 @@ namespace {

// extract piece length
std::int64_t const piece_length = info.dict_find_int_value("piece length", -1);
// limit the piece length at INT_MAX / 2 to get a bit of headroom. We
// commonly compute the number of blocks per pieces by adding
// block_size - 1 before dividing by block_size. That would overflow with
// a piece size of INT_MAX. This limit is still an unreasonably large
// piece size anyway.
if (piece_length <= 0 || piece_length > std::numeric_limits<int>::max() / 2)
if (piece_length <= 0 || piece_length > file_storage::max_piece_size)
{
ec = errors::torrent_missing_piece_length;
return false;
Expand Down Expand Up @@ -1285,8 +1280,7 @@ namespace {
// we want this division to round upwards, that's why we have the
// extra addition

if (files.total_size() / files.piece_length() >=
std::numeric_limits<int>::max())
if (files.total_size() / files.piece_length() > file_storage::max_num_pieces)
{
ec = errors::too_many_pieces_in_torrent;
// mark the torrent as invalid
Expand Down
21 changes: 12 additions & 9 deletions test/test_torrent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,15 +161,18 @@ void test_large_piece_size(int const size)
info["piece length"] = size;
info["length"] = size;

std::vector<char> const buf = bencode(torrent);
add_torrent_params atp = load_torrent_buffer(buf);
atp.save_path = ".";

lt::session ses;
auto h = ses.add_torrent(std::move(atp));
TEST_CHECK(h.status().errc == error_code(lt::errors::invalid_piece_size));
h.clear_error();
TEST_CHECK(h.status().errc == error_code(lt::errors::invalid_piece_size));
std::vector<char> buf;
bencode(std::back_inserter(buf), torrent);
try
{
add_torrent_params atp = load_torrent_buffer(buf);
// we expect this to fail with an exception
TEST_CHECK(false);
}
catch (lt::system_error const& e)
{
TEST_CHECK(e.code() == error_code(lt::errors::torrent_missing_piece_length));
}
}

} // anonymous namespace
Expand Down
6 changes: 5 additions & 1 deletion test/test_torrent_info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,10 @@ static test_torrent_t const test_torrents[] =
TEST_CHECK((atp.dht_nodes == std::vector<np>{np("127.0.0.1", 6881), np("192.168.1.1", 6881)}));
}
},
{ "large_piece_size.torrent", [](lt::add_torrent_params atp) {
TEST_EQUAL(atp.ti->piece_length(), (32767 * 0x4000));
}
},
};

struct test_failing_torrent_t
Expand Down Expand Up @@ -945,7 +949,7 @@ void sanity_check(std::shared_ptr<torrent_info const> const& ti)
// for it, it's still no good.
aux::piece_picker pp(ti->total_size(), ti->piece_length());

TEST_CHECK(ti->piece_length() < std::numeric_limits<int>::max() / 2);
TEST_CHECK(ti->piece_length() <= file_storage::max_piece_size);
TEST_EQUAL(ti->v1(), ti->info_hashes().has_v1());
TEST_EQUAL(ti->v2(), ti->info_hashes().has_v2());
}
Expand Down
1 change: 1 addition & 0 deletions test/test_torrents/large_piece_size.torrent
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
d10:created by10:libtorrent13:creation datei1359599503e4:infod6:lengthi425e4:name4:temp12:piece lengthi536854528e6:pieces20:����&��JW�}�A4u,����ee
4 changes: 3 additions & 1 deletion test/web_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,9 @@ def inner_do_GET(self):
http_handler.protocol_version = 'HTTP/1.1'
httpd = http_server_with_timeout(('127.0.0.1', port), http_handler)
if use_ssl:
httpd.socket = ssl.wrap_socket(httpd.socket, certfile='../ssl/server.pem', server_side=True)
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ctx.load_cert_chain("../ssl/server.pem")
httpd.socket = ctx.wrap_socket(httpd.socket, server_side=True)

while True:
httpd.handle_request()

0 comments on commit 5f5f8e0

Please sign in to comment.