diff --git a/ChangeLog b/ChangeLog index c6f5c713e..1ccd642b9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -25,6 +25,7 @@ * fix uTP edge case where udp socket buffer fills up * fix nagle implementation in uTP + * fix issue when loading certain malformed .torrent files * pass along host header with http proxy requests and possible http_connection shutdown hang 0.16.12 release diff --git a/src/file.cpp b/src/file.cpp index 4da0e751d..7682e45a4 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -409,16 +409,33 @@ namespace libtorrent std::string extension(std::string const& f) { - char const* ext = strrchr(f.c_str(), '.'); - if (ext == 0) return ""; - return ext; + for (int i = f.size() - 1; i >= 0; --i) + { + if (f[i] == '/') break; +#ifdef TORRENT_WINDOWS + if (f[i] == '\\') break; +#endif + if (f[i] != '.') continue; + return f.substr(i); + } + return ""; } void replace_extension(std::string& f, std::string const& ext) { - char const* e = strrchr(f.c_str(), '.'); - if (e == 0) f += '.'; - else f.resize(e - f.c_str() + 1); + for (int i = f.size() - 1; i >= 0; --i) + { + if (f[i] == '/') break; +#ifdef TORRENT_WINDOWS + if (f[i] == '\\') break; +#endif + + if (f[i] != '.') continue; + + f.resize(i); + break; + } + f += '.'; f += ext; } diff --git a/src/torrent_info.cpp b/src/torrent_info.cpp index 078dddaa5..794d11db9 100644 --- a/src/torrent_info.cpp +++ b/src/torrent_info.cpp @@ -308,6 +308,8 @@ namespace libtorrent if (p->list_at(i)->type() != lazy_entry::string_t) return false; std::string path_element = p->list_at(i)->string_value(); + if (path_element.empty()) + path_element = "_"; if (!valid_path_element(path_element)) continue; if (i == end - 1) *filename = p->list_at(i); trim_path_element(path_element); diff --git a/test/test_file.cpp b/test/test_file.cpp index d79b0124c..8b620a471 100644 --- a/test/test_file.cpp +++ b/test/test_file.cpp @@ -125,6 +125,7 @@ int test_main() TEST_EQUAL(extension("blah.exe"), ".exe"); TEST_EQUAL(extension("blah.foo.bar"), ".bar"); TEST_EQUAL(extension("blah.foo."), "."); + TEST_EQUAL(extension("blah.foo/bar"), ""); TEST_EQUAL(filename("blah"), "blah"); TEST_EQUAL(filename("/blah/foo/bar"), "bar"); @@ -209,6 +210,15 @@ int test_main() replace_extension(test, "txt"); TEST_EQUAL(test, "foo.txt"); + test = "_"; + replace_extension(test, "txt"); + TEST_EQUAL(test, "_.txt"); + + test = "1.2.3/_"; + replace_extension(test, "txt"); + TEST_EQUAL(test, "1.2.3/_.txt"); + + // file class file f; #if TORRENT_USE_UNC_PATHS || !defined WIN32 diff --git a/test/test_torrent_parse.cpp b/test/test_torrent_parse.cpp index 7ae65b834..9b98f276a 100644 --- a/test/test_torrent_parse.cpp +++ b/test/test_torrent_parse.cpp @@ -71,6 +71,7 @@ test_torrent_t test_torrents[] = { "url_seed_multi_space.torrent" }, { "url_seed_multi_space_nolist.torrent" }, { "root_hash.torrent" }, + { "empty_path_multi.torrent" }, }; struct test_failing_torrent_t diff --git a/test/test_torrents/empty_path_multi.torrent b/test/test_torrents/empty_path_multi.torrent new file mode 100644 index 000000000..59815da8d --- /dev/null +++ b/test/test_torrents/empty_path_multi.torrent @@ -0,0 +1 @@ +d10:created by10:libtorrent13:creation datei1359599503e4:infod5:filesld6:lengthi425e4:pathl5:abcdeeed6:lengthi3e4:pathl0:eed6:lengthi5e4:pathl0:eee4:name4:temp12:piece lengthi16384e6:pieces20:‚ž¼Œ&¾ÇJW›}ÜA4u,·¼‘‡ee