forked from premiere/premiere-libtorrent
fix infinite loop when parsing torrents whose filenames have zeroes. #2247
This commit is contained in:
parent
fcb9c7b6f3
commit
b70d3efba9
2
AUTHORS
2
AUTHORS
|
@ -14,6 +14,8 @@ Stas Khirman
|
||||||
Ryan Norton
|
Ryan Norton
|
||||||
Andrew Resch
|
Andrew Resch
|
||||||
|
|
||||||
|
Thanks to (github user) nervoir for bug reports
|
||||||
|
|
||||||
Building and maintainance of the autotools scripts:
|
Building and maintainance of the autotools scripts:
|
||||||
Michael Wojciechowski
|
Michael Wojciechowski
|
||||||
Peter Koeleman
|
Peter Koeleman
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
* fix infinite loop when parsing maliciously crafted torrents
|
||||||
* fix invalid read in parse_int in bdecoder
|
* fix invalid read in parse_int in bdecoder
|
||||||
* fix issue with very long tracker- and web seed URLs
|
* fix issue with very long tracker- and web seed URLs
|
||||||
* don't attempt to create empty files on startup, if they already exist
|
* don't attempt to create empty files on startup, if they already exist
|
||||||
|
|
|
@ -103,6 +103,18 @@ namespace libtorrent
|
||||||
bool is_i2p_url(std::string const& url);
|
bool is_i2p_url(std::string const& url);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// this can be used as the hash function in std::unordered_*
|
||||||
|
struct TORRENT_EXTRA_EXPORT string_hash_no_case
|
||||||
|
{ size_t operator()(std::string const& s) const; };
|
||||||
|
|
||||||
|
// these can be used as the comparison functions in std::map and std::set
|
||||||
|
struct TORRENT_EXTRA_EXPORT string_eq_no_case
|
||||||
|
{ bool operator()(std::string const& lhs, std::string const& rhs) const; };
|
||||||
|
|
||||||
|
struct TORRENT_EXTRA_EXPORT string_less_no_case
|
||||||
|
{ bool operator()(std::string const& lhs, std::string const& rhs) const; };
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -277,5 +277,48 @@ namespace libtorrent
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
std::size_t string_hash_no_case::operator()(std::string const& s) const
|
||||||
|
{
|
||||||
|
size_t ret = 5381;
|
||||||
|
for (std::string::const_iterator i = s.begin(); i != s.end(); ++i)
|
||||||
|
ret = (ret * 33) ^ to_lower(*i);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool string_eq_no_case::operator()(std::string const& lhs, std::string const& rhs) const
|
||||||
|
{
|
||||||
|
if (lhs.size() != rhs.size()) return false;
|
||||||
|
|
||||||
|
std::string::const_iterator s1 = lhs.begin();
|
||||||
|
std::string::const_iterator s2 = rhs.begin();
|
||||||
|
|
||||||
|
while (s1 != lhs.end() && s2 != rhs.end())
|
||||||
|
{
|
||||||
|
if (to_lower(*s1) != to_lower(*s2)) return false;
|
||||||
|
++s1;
|
||||||
|
++s2;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool string_less_no_case::operator()(std::string const& lhs, std::string const& rhs) const
|
||||||
|
{
|
||||||
|
std::string::const_iterator s1 = lhs.begin();
|
||||||
|
std::string::const_iterator s2 = rhs.begin();
|
||||||
|
|
||||||
|
while (s1 != lhs.end() && s2 != rhs.end())
|
||||||
|
{
|
||||||
|
char const c1 = to_lower(*s1);
|
||||||
|
char const c2 = to_lower(*s2);
|
||||||
|
if (c1 < c2) return true;
|
||||||
|
if (c1 > c2) return false;
|
||||||
|
++s1;
|
||||||
|
++s2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is the tie-breaker
|
||||||
|
return lhs.size() < rhs.size();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -497,65 +497,6 @@ namespace libtorrent
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TORRENT_HAS_BOOST_UNORDERED
|
|
||||||
struct string_hash_no_case
|
|
||||||
{
|
|
||||||
size_t operator()(std::string const& s) const
|
|
||||||
{
|
|
||||||
char const* s1 = s.c_str();
|
|
||||||
size_t ret = 5381;
|
|
||||||
int c;
|
|
||||||
|
|
||||||
while ((c = *s1++))
|
|
||||||
ret = (ret * 33) ^ to_lower(c);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct string_eq_no_case
|
|
||||||
{
|
|
||||||
bool operator()(std::string const& lhs, std::string const& rhs) const
|
|
||||||
{
|
|
||||||
char c1, c2;
|
|
||||||
char const* s1 = lhs.c_str();
|
|
||||||
char const* s2 = rhs.c_str();
|
|
||||||
|
|
||||||
while (*s1 != 0 && *s2 != 0)
|
|
||||||
{
|
|
||||||
c1 = to_lower(*s1);
|
|
||||||
c2 = to_lower(*s2);
|
|
||||||
if (c1 != c2) return false;
|
|
||||||
++s1;
|
|
||||||
++s2;
|
|
||||||
}
|
|
||||||
return *s1 == *s2;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#else
|
|
||||||
struct string_less_no_case
|
|
||||||
{
|
|
||||||
bool operator()(std::string const& lhs, std::string const& rhs) const
|
|
||||||
{
|
|
||||||
char c1, c2;
|
|
||||||
char const* s1 = lhs.c_str();
|
|
||||||
char const* s2 = rhs.c_str();
|
|
||||||
|
|
||||||
while (*s1 != 0 || *s2 != 0)
|
|
||||||
{
|
|
||||||
c1 = to_lower(*s1);
|
|
||||||
c2 = to_lower(*s2);
|
|
||||||
if (c1 < c2) return true;
|
|
||||||
if (c1 > c2) return false;
|
|
||||||
++s1;
|
|
||||||
++s2;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// root_dir is the name of the torrent, unless this is a single file
|
// root_dir is the name of the torrent, unless this is a single file
|
||||||
// torrent, in which case it's empty.
|
// torrent, in which case it's empty.
|
||||||
bool extract_files(bdecode_node const& list, file_storage& target
|
bool extract_files(bdecode_node const& list, file_storage& target
|
||||||
|
|
|
@ -310,3 +310,70 @@ TORRENT_TEST(string)
|
||||||
, convert_to_native("foo") + convert_to_native("bar"));
|
, convert_to_native("foo") + convert_to_native("bar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TORRENT_TEST(string_hash_no_case)
|
||||||
|
{
|
||||||
|
string_hash_no_case hsh;
|
||||||
|
|
||||||
|
// make sure different strings yield different hashes
|
||||||
|
TEST_CHECK(hsh("ab") != hsh("ba"));
|
||||||
|
|
||||||
|
// make sure case is ignored
|
||||||
|
TEST_EQUAL(hsh("Ab"), hsh("ab"));
|
||||||
|
TEST_EQUAL(hsh("Ab"), hsh("aB"));
|
||||||
|
|
||||||
|
// make sure zeroes in strings are supported
|
||||||
|
TEST_CHECK(hsh(std::string("\0a", 2)) != hsh(std::string("\0b", 2)));
|
||||||
|
TEST_EQUAL(hsh(std::string("\0a", 2)), hsh(std::string("\0a", 2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TORRENT_TEST(string_eq_no_case)
|
||||||
|
{
|
||||||
|
string_eq_no_case cmp;
|
||||||
|
TEST_CHECK(cmp("ab", "ba") == false);
|
||||||
|
TEST_CHECK(cmp("", ""));
|
||||||
|
TEST_CHECK(cmp("abc", "abc"));
|
||||||
|
|
||||||
|
// make sure different lengths are correctly treated as different
|
||||||
|
TEST_CHECK(cmp("abc", "ab") == false);
|
||||||
|
|
||||||
|
// make sure case is ignored
|
||||||
|
TEST_CHECK(cmp("Ab", "ab"));
|
||||||
|
TEST_CHECK(cmp("Ab", "aB"));
|
||||||
|
|
||||||
|
// make sure zeros are supported
|
||||||
|
TEST_CHECK(cmp(std::string("\0a", 2), std::string("\0b", 2)) == false);
|
||||||
|
TEST_CHECK(cmp(std::string("\0a", 2), std::string("\0a", 2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TORRENT_TEST(string_less_no_case)
|
||||||
|
{
|
||||||
|
string_less_no_case cmp;
|
||||||
|
// ab < ba
|
||||||
|
TEST_CHECK(cmp("ab", "ba"));
|
||||||
|
TEST_CHECK(cmp("ba", "ab") == false);
|
||||||
|
|
||||||
|
TEST_CHECK(cmp("", "") == false);
|
||||||
|
TEST_CHECK(cmp("", "a"));
|
||||||
|
TEST_CHECK(cmp("abc", "abc") == false);
|
||||||
|
|
||||||
|
// shorter strings come before longer ones
|
||||||
|
TEST_CHECK(cmp("abc", "ab") == false);
|
||||||
|
TEST_CHECK(cmp("ab", "abc"));
|
||||||
|
|
||||||
|
// make sure case is ignored
|
||||||
|
TEST_CHECK(cmp("Ab", "ba"));
|
||||||
|
TEST_CHECK(cmp("Ba", "ab") == false);
|
||||||
|
|
||||||
|
TEST_CHECK(cmp("", "") == false);
|
||||||
|
TEST_CHECK(cmp("", "a"));
|
||||||
|
TEST_CHECK(cmp("abc", "Abc") == false);
|
||||||
|
|
||||||
|
// shorter strings come before longer ones
|
||||||
|
TEST_CHECK(cmp("Abc", "ab") == false);
|
||||||
|
TEST_CHECK(cmp("Ab", "abc"));
|
||||||
|
|
||||||
|
// make sure zeros are supported
|
||||||
|
TEST_CHECK(cmp(std::string("\0a", 2), std::string("\0b", 2)));
|
||||||
|
TEST_CHECK(cmp(std::string("\0a", 2), std::string("\0a", 2)) == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue