From 18e5d6796799d87799292fcbefc9e612267747d7 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Thu, 26 Nov 2009 00:09:49 +0000 Subject: [PATCH] protect file_priority functions from being called on torrents without metadata --- docs/manual.rst | 4 ++++ include/libtorrent/lazy_entry.hpp | 22 ++++++++++++++++++++++ src/torrent.cpp | 7 +++++++ src/torrent_info.cpp | 14 ++++++++++++++ 4 files changed, 47 insertions(+) diff --git a/docs/manual.rst b/docs/manual.rst index 85ecae58c..8bfe7781c 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -2084,6 +2084,10 @@ Whenever a file priority is changed, all other piece priorities are reset to match the file priorities. In order to maintain sepcial priorities for particular pieces, ``piece_priority`` has to be called again for those pieces. +You cannot set the file priorities on a torrent that does not yet +have metadata or a torrent that is a seed. ``file_priority(int, int)`` and +``prioritize_files()`` are both no-ops for such torrents. + file_progress() --------------- diff --git a/include/libtorrent/lazy_entry.hpp b/include/libtorrent/lazy_entry.hpp index cb5678181..4fff0f63c 100644 --- a/include/libtorrent/lazy_entry.hpp +++ b/include/libtorrent/lazy_entry.hpp @@ -53,6 +53,18 @@ namespace libtorrent // return 0 = success TORRENT_EXPORT int lazy_bdecode(char const* start, char const* end, lazy_entry& ret, int depth_limit = 1000); + struct pascal_string + { + pascal_string(char const* p, int l): len(l), ptr(p) {} + int len; + char const* ptr; + bool operator<(pascal_string const& rhs) const + { + return memcmp(ptr, rhs.ptr, (std::min)(len, rhs.len)) < 0 + || len < rhs.len; + } + }; + struct TORRENT_EXPORT lazy_entry { enum entry_type_t @@ -100,6 +112,12 @@ namespace libtorrent return m_data.start; } + pascal_string string_pstr() const + { + TORRENT_ASSERT(m_type == string_t); + return pascal_string(m_data.start, m_size); + } + std::string string_value() const { TORRENT_ASSERT(m_type == string_t); @@ -228,6 +246,10 @@ namespace libtorrent // in the original buffer they are based on char const* m_begin; char const* m_end; + + // non-copyable + lazy_entry(lazy_entry const&); + lazy_entry const& operator=(lazy_entry const&); }; TORRENT_EXPORT std::string print_entry(lazy_entry const& e, bool single_line = false); diff --git a/src/torrent.cpp b/src/torrent.cpp index 3faa91967..6d0004e33 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -2617,6 +2617,10 @@ namespace libtorrent void torrent::set_file_priority(int index, int prio) { INVARIANT_CHECK; + + // this call is only valid on torrents with metadata + if (!valid_metadata() || is_seed()) return; + TORRENT_ASSERT(index < m_torrent_file->num_files()); TORRENT_ASSERT(index >= 0); if (m_file_priority[index] == prio) return; @@ -2626,6 +2630,9 @@ namespace libtorrent int torrent::file_priority(int index) const { + // this call is only valid on torrents with metadata + if (!valid_metadata()) return 1; + TORRENT_ASSERT(index < m_torrent_file->num_files()); TORRENT_ASSERT(index >= 0); return m_file_priority[index]; diff --git a/src/torrent_info.cpp b/src/torrent_info.cpp index d11ac2dc5..32857ffa8 100644 --- a/src/torrent_info.cpp +++ b/src/torrent_info.cpp @@ -303,6 +303,17 @@ namespace libtorrent return true; } + struct pascal_string + { + int len; + char const* ptr; + bool operator<(pascal_string const& rhs) const + { + return memcmp(ptr, rhs.ptr, (std::min)(len, rhs.len)) < 0 + || len < rhs.len; + } + }; + bool extract_files(lazy_entry const& list, file_storage& target , std::string const& root_dir) { @@ -313,6 +324,9 @@ namespace libtorrent if (!extract_single_file(*list.list_at(i), e, root_dir)) return false; int cnt = 0; + std::set files; + pascal_string = + while (!files.insert(path).second) for (file_storage::iterator k = target.begin() , end(target.end()); k != end; ++k) {