diff --git a/ChangeLog b/ChangeLog index 8f698fbbc..6b1841658 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * fix crash caused by empty bitfield * removed disk-access-log build configuration * removed mmap_cache feature * strengthened type safety in handling of piece and file indices diff --git a/include/libtorrent/bitfield.hpp b/include/libtorrent/bitfield.hpp index e38f9a144..387a79a79 100644 --- a/include/libtorrent/bitfield.hpp +++ b/include/libtorrent/bitfield.hpp @@ -105,6 +105,8 @@ namespace libtorrent bool none_set() const { + if(size() == 0) return true; + const int words = num_words(); std::uint32_t const* b = buf(); for (int i = 0; i < words; ++i) @@ -126,7 +128,7 @@ namespace libtorrent } // returns true if the bitfield has zero size. - bool empty() const { return m_buf == nullptr ? true : m_buf[0] == 0; } + bool empty() const { return size() == 0; } // returns a pointer to the internal buffer of the bitfield. char const* data() const { return m_buf ? reinterpret_cast(&m_buf[1]) : nullptr; } @@ -226,13 +228,13 @@ namespace libtorrent // set all bits in the bitfield to 1 (set_all) or 0 (clear_all). void set_all() { - if (m_buf == nullptr) return; + if (size() == 0) return; std::memset(buf(), 0xff, size_t(num_words() * 4)); clear_trailing_bits(); } void clear_all() { - if (m_buf == nullptr) return; + if (size() == 0) return; std::memset(buf(), 0x00, size_t(num_words() * 4)); } diff --git a/src/bitfield.cpp b/src/bitfield.cpp index a9ca8f112..c9fbcfccc 100644 --- a/src/bitfield.cpp +++ b/src/bitfield.cpp @@ -41,6 +41,8 @@ namespace libtorrent { bool bitfield::all_set() const { + if(size() == 0) return false; + int const words = size() / 32; for (int i = 1; i < words + 1; ++i) { diff --git a/test/test_bitfield.cpp b/test/test_bitfield.cpp index fc8763a41..ae711e076 100644 --- a/test/test_bitfield.cpp +++ b/test/test_bitfield.cpp @@ -355,3 +355,51 @@ TORRENT_TEST(find_last_clear_misc) test4.clear_bit(89); TEST_EQUAL(test4.find_last_clear(), 91); } + +TORRENT_TEST(not_initialized) +{ + // check a not initialized empty bitfield + bitfield test1(0); + TEST_EQUAL(test1.none_set(), true); + TEST_EQUAL(test1.all_set(), false); + TEST_EQUAL(test1.size(), 0); + TEST_EQUAL(test1.num_words(), 0); + TEST_EQUAL(test1.empty(), true); + TEST_CHECK(test1.data() == nullptr); + TEST_EQUAL(test1.count(), 0); + TEST_EQUAL(test1.find_first_set(), -1); + TEST_EQUAL(test1.find_last_clear(), -1); + + test1.clear_all(); + TEST_EQUAL(test1.size(), 0); + + test1.clear(); + TEST_EQUAL(test1.size(), 0); + + test1.set_all(); + TEST_EQUAL(test1.size(), 0); + + // don't test methods which aren't defined for empty sets: + // get_bit, clear_bit, set_bit +} + +TORRENT_TEST(not_initialized_assign) +{ + // check a not initialized empty bitfield + bitfield test1(0); + std::uint8_t b1[] = { 0xff }; + test1.assign((char*)b1, 8); + TEST_EQUAL(test1.count(), 8); +} + +TORRENT_TEST(not_initialized_resize) +{ + // check a not initialized empty bitfield + bitfield test1(0); + test1.resize(8, true); + TEST_EQUAL(test1.count(), 8); + + bitfield test2(0); + test2.resize(8); + TEST_EQUAL(test2.size(), 8); +} \ No newline at end of file