From c1955ecb181a6ab5ba0e8f21d84f33e3493a0c62 Mon Sep 17 00:00:00 2001 From: arvidn Date: Thu, 1 Oct 2015 01:05:00 -0400 Subject: [PATCH] fix bug in parse_magnet_uri and improve unit test --- src/magnet_uri.cpp | 16 ++- test/test_magnet.cpp | 300 ++++++++++++++++++++++++++----------------- 2 files changed, 196 insertions(+), 120 deletions(-) diff --git a/src/magnet_uri.cpp b/src/magnet_uri.cpp index a2eb47fc1..959ce69e8 100644 --- a/src/magnet_uri.cpp +++ b/src/magnet_uri.cpp @@ -251,7 +251,21 @@ namespace libtorrent sha1_hash info_hash; if (btih.size() == 40 + 9) from_hex(&btih[9], 40, info_hash.data()); - else info_hash.assign(base32decode(btih.substr(9))); + else if (btih.size() == 32 + 9) + { + std::string ih = base32decode(btih.substr(9)); + if (ih.size() != 20) + { + ec = errors::invalid_info_hash; + return; + } + info_hash.assign(ih); + } + else + { + ec = errors::invalid_info_hash; + return; + } p.info_hash = info_hash; if (!name.empty()) p.name = name; diff --git a/test/test_magnet.cpp b/test/test_magnet.cpp index 5d7d38883..62494038d 100644 --- a/test/test_magnet.cpp +++ b/test/test_magnet.cpp @@ -59,11 +59,21 @@ void test_remove_url(std::string url) TEST_EQUAL(handles.size(), 0); } +TORRENT_TEST(remove_url) +{ + test_remove_url("magnet:?xt=urn:btih:0123456789abcdef0123456789abcdef01234567"); +} + +TORRENT_TEST(remove_url2) +{ + test_remove_url("http://non-existent.com/test.torrent"); +} + TORRENT_TEST(magnet) { session_proxy p1; session_proxy p2; - { + // test session state load/restore settings_pack pack; pack.set_str(settings_pack::user_agent, "test"); @@ -73,11 +83,10 @@ TORRENT_TEST(magnet) pack.set_int(settings_pack::initial_picker_threshold, 351); pack.set_bool(settings_pack::upnp_ignore_nonrouters, true); pack.set_bool(settings_pack::coalesce_writes, true); - pack.set_int(settings_pack::auto_scrape_interval, 753); pack.set_bool(settings_pack::close_redundant_connections, false); pack.set_int(settings_pack::auto_scrape_interval, 235); pack.set_int(settings_pack::auto_scrape_min_interval, 62); - lt::session* s = new lt::session(pack); + boost::scoped_ptr s(new lt::session(pack)); TEST_EQUAL(pack.get_str(settings_pack::user_agent), "test"); TEST_EQUAL(pack.get_int(settings_pack::tracker_receive_timeout), 1234); @@ -167,8 +176,7 @@ TORRENT_TEST(magnet) TEST_EQUAL(to_hex(t.info_hash().to_string()), "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"); p1 = s->abort(); - delete s; - s = new lt::session(); + s.reset(new lt::session()); std::vector buf; bencode(std::back_inserter(buf), session_state); @@ -178,34 +186,6 @@ TORRENT_TEST(magnet) fprintf(stderr, "session_state\n%s\n", print_entry(session_state2).c_str()); - // parse_magnet_uri - parse_magnet_uri("magnet:?dn=foo&dht=127.0.0.1:43", p, ec); - TEST_CHECK(ec == error_code(errors::missing_info_hash_in_uri)); - ec.clear(); - - // parse_magnet_uri - parse_magnet_uri("magnet:?xt=urn:btih:cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd&ws=http://foo.com/bar&ws=http://bar.com/foo", p, ec); - TEST_CHECK(!ec); - TEST_EQUAL(p.url_seeds.size(), 2); - TEST_EQUAL(p.url_seeds[0], "http://foo.com/bar"); - TEST_EQUAL(p.url_seeds[1], "http://bar.com/foo"); - ec.clear(); - - parse_magnet_uri("magnet:?xt=blah&dn=foo&dht=127.0.0.1:43", p, ec); - TEST_CHECK(ec == error_code(errors::missing_info_hash_in_uri)); - ec.clear(); - -#ifndef TORRENT_DISABLE_DHT - parse_magnet_uri("magnet:?xt=urn:btih:cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd&dn=foo&dht=127.0.0.1:43", p, ec); - TEST_CHECK(!ec); - if (ec) fprintf(stderr, "%s\n", ec.message().c_str()); - ec.clear(); - - TEST_CHECK(p.dht_nodes.size() == 1); - TEST_CHECK(p.dht_nodes[0].first == "127.0.0.1"); - TEST_CHECK(p.dht_nodes[0].second == 43); -#endif - // make sure settings that haven't been changed from their defaults are not saved TEST_CHECK(session_state2.dict_find("settings") .dict_find("optimistic_disk_retry") == 0); @@ -222,93 +202,175 @@ TORRENT_TEST(magnet) CMP_SET(urlseed_wait_retry); CMP_SET(initial_picker_threshold); CMP_SET(auto_scrape_interval); - CMP_SET(auto_scrape_interval); CMP_SET(auto_scrape_min_interval); p2 = s->abort(); - delete s; - } - - // make_magnet_uri - { - entry info; - info["pieces"] = "aaaaaaaaaaaaaaaaaaaa"; - info["name"] = "slightly shorter name, it's kind of sad that people started the trend of incorrectly encoding the regular name field and then adding another one with correct encoding"; - info["name.utf-8"] = "this is a long ass name in order to try to make make_magnet_uri overflow and hopefully crash. Although, by the time you read this that particular bug should have been fixed"; - info["piece length"] = 16 * 1024; - info["length"] = 3245; - entry torrent; - torrent["info"] = info; - entry::list_type& al1 = torrent["announce-list"].list(); - al1.push_back(entry::list_type()); - entry::list_type& al = al1.back().list(); - al.push_back(entry("http://bigtorrent.org:2710/announce")); - al.push_back(entry("http://bt.careland.com.cn:6969/announce")); - al.push_back(entry("http://bt.e-burg.org:2710/announce")); - al.push_back(entry("http://bttrack.9you.com/announce")); - al.push_back(entry("http://coppersurfer.tk:6969/announce")); - al.push_back(entry("http://erdgeist.org/arts/software/opentracker/announce")); - al.push_back(entry("http://exodus.desync.com/announce")); - al.push_back(entry("http://fr33dom.h33t.com:3310/announce")); - al.push_back(entry("http://genesis.1337x.org:1337/announce")); - al.push_back(entry("http://inferno.demonoid.me:3390/announce")); - al.push_back(entry("http://inferno.demonoid.ph:3390/announce")); - al.push_back(entry("http://ipv6.tracker.harry.lu/announce")); - al.push_back(entry("http://lnxroot.com:6969/announce")); - al.push_back(entry("http://nemesis.1337x.org/announce")); - al.push_back(entry("http://puto.me:6969/announce")); - al.push_back(entry("http://sline.net:2710/announce")); - al.push_back(entry("http://tracker.beeimg.com:6969/announce")); - al.push_back(entry("http://tracker.ccc.de/announce")); - al.push_back(entry("http://tracker.coppersurfer.tk/announce")); - al.push_back(entry("http://tracker.coppersurfer.tk:6969/announce")); - al.push_back(entry("http://tracker.cpleft.com:2710/announce")); - al.push_back(entry("http://tracker.istole.it/announce")); - al.push_back(entry("http://tracker.kamyu.net/announce")); - al.push_back(entry("http://tracker.novalayer.org:6969/announce")); - al.push_back(entry("http://tracker.torrent.to:2710/announce")); - al.push_back(entry("http://tracker.torrentbay.to:6969/announce")); - al.push_back(entry("udp://tracker.openbittorrent.com:80")); - al.push_back(entry("udp://tracker.publicbt.com:80")); - - std::vector buf; - bencode(std::back_inserter(buf), torrent); - buf.push_back('\0'); - printf("%s\n", &buf[0]); - error_code ec; - torrent_info ti(&buf[0], buf.size(), ec); - - TEST_EQUAL(al.size(), ti.trackers().size()); - - std::string magnet = make_magnet_uri(ti); - printf("%s len: %d\n", magnet.c_str(), int(magnet.size())); - } - - // make_magnet_uri - { - entry info; - info["pieces"] = "aaaaaaaaaaaaaaaaaaaa"; - info["name"] = "test"; - info["name.utf-8"] = "test"; - info["piece length"] = 16 * 1024; - info["length"] = 3245; - entry torrent; - torrent["info"] = info; - - torrent["url-list"] = "http://foo.com/bar"; - - std::vector buf; - bencode(std::back_inserter(buf), torrent); - buf.push_back('\0'); - printf("%s\n", &buf[0]); - error_code ec; - torrent_info ti(&buf[0], buf.size(), ec); - - std::string magnet = make_magnet_uri(ti); - printf("%s len: %d\n", magnet.c_str(), int(magnet.size())); - TEST_CHECK(magnet.find("&ws=http%3a%2f%2ffoo.com%2fbar") != std::string::npos); - } - - test_remove_url("magnet:?xt=urn:btih:0123456789abcdef0123456789abcdef01234567"); - test_remove_url("http://non-existent.com/test.torrent"); +} + +TORRENT_TEST(parse_missing_hash) +{ + // parse_magnet_uri + error_code ec; + add_torrent_params p; + parse_magnet_uri("magnet:?dn=foo&dht=127.0.0.1:43", p, ec); + TEST_EQUAL(ec, error_code(errors::missing_info_hash_in_uri)); + ec.clear(); +} + +TORRENT_TEST(parse_base32_hash) +{ + // parse_magnet_uri + error_code ec; + add_torrent_params p; + parse_magnet_uri("magnet:?xt=urn:btih:MFRGCYTBMJQWEYLCMFRGCYTBMJQWEYLC", p, ec); + TEST_CHECK(!ec); + TEST_EQUAL(p.info_hash, sha1_hash("abababababababababab")); + ec.clear(); +} + +TORRENT_TEST(parse_web_seeds) +{ + // parse_magnet_uri + error_code ec; + add_torrent_params p; + parse_magnet_uri("magnet:?xt=urn:btih:cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd&ws=http://foo.com/bar&ws=http://bar.com/foo", p, ec); + TEST_CHECK(!ec); + TEST_EQUAL(p.url_seeds.size(), 2); + TEST_EQUAL(p.url_seeds[0], "http://foo.com/bar"); + TEST_EQUAL(p.url_seeds[1], "http://bar.com/foo"); + ec.clear(); +} + +TORRENT_TEST(parse_missing_hash2) +{ + error_code ec; + add_torrent_params p; + parse_magnet_uri("magnet:?xt=blah&dn=foo&dht=127.0.0.1:43", p, ec); + TEST_EQUAL(ec, error_code(errors::missing_info_hash_in_uri)); + ec.clear(); +} + +TORRENT_TEST(parse_short_hash) +{ + error_code ec; + add_torrent_params p; + parse_magnet_uri("magnet:?xt=urn:btih:abababab", p, ec); + TEST_EQUAL(ec, error_code(errors::invalid_info_hash)); + ec.clear(); +} + +TORRENT_TEST(parse_long_hash) +{ + error_code ec; + add_torrent_params p; + parse_magnet_uri("magnet:?xt=urn:btih:ababababababababababab", p, ec); + TEST_EQUAL(ec, error_code(errors::invalid_info_hash)); + ec.clear(); +} + +TORRENT_TEST(parse_space_hash) +{ + error_code ec; + add_torrent_params p; + parse_magnet_uri("magnet:?xt=urn:btih: abababababababababab", p, ec); + TEST_EQUAL(ec, error_code(errors::invalid_info_hash)); + ec.clear(); +} + +#ifndef TORRENT_DISABLE_DHT +TORRENT_TEST(parse_dht_node) +{ + error_code ec; + add_torrent_params p; + parse_magnet_uri("magnet:?xt=urn:btih:cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd&dn=foo&dht=127.0.0.1:43", p, ec); + TEST_CHECK(!ec); + if (ec) fprintf(stderr, "%s\n", ec.message().c_str()); + ec.clear(); + + TEST_EQUAL(p.dht_nodes.size(), 1); + TEST_EQUAL(p.dht_nodes[0].first, "127.0.0.1"); + TEST_EQUAL(p.dht_nodes[0].second, 43); +} +#endif + +TORRENT_TEST(make_magnet_uri) +{ + // make_magnet_uri + entry info; + info["pieces"] = "aaaaaaaaaaaaaaaaaaaa"; + info["name"] = "slightly shorter name, it's kind of sad that people started the trend of incorrectly encoding the regular name field and then adding another one with correct encoding"; + info["name.utf-8"] = "this is a long ass name in order to try to make make_magnet_uri overflow and hopefully crash. Although, by the time you read this that particular bug should have been fixed"; + info["piece length"] = 16 * 1024; + info["length"] = 3245; + entry torrent; + torrent["info"] = info; + entry::list_type& al1 = torrent["announce-list"].list(); + al1.push_back(entry::list_type()); + entry::list_type& al = al1.back().list(); + al.push_back(entry("http://bigtorrent.org:2710/announce")); + al.push_back(entry("http://bt.careland.com.cn:6969/announce")); + al.push_back(entry("http://bt.e-burg.org:2710/announce")); + al.push_back(entry("http://bttrack.9you.com/announce")); + al.push_back(entry("http://coppersurfer.tk:6969/announce")); + al.push_back(entry("http://erdgeist.org/arts/software/opentracker/announce")); + al.push_back(entry("http://exodus.desync.com/announce")); + al.push_back(entry("http://fr33dom.h33t.com:3310/announce")); + al.push_back(entry("http://genesis.1337x.org:1337/announce")); + al.push_back(entry("http://inferno.demonoid.me:3390/announce")); + al.push_back(entry("http://inferno.demonoid.ph:3390/announce")); + al.push_back(entry("http://ipv6.tracker.harry.lu/announce")); + al.push_back(entry("http://lnxroot.com:6969/announce")); + al.push_back(entry("http://nemesis.1337x.org/announce")); + al.push_back(entry("http://puto.me:6969/announce")); + al.push_back(entry("http://sline.net:2710/announce")); + al.push_back(entry("http://tracker.beeimg.com:6969/announce")); + al.push_back(entry("http://tracker.ccc.de/announce")); + al.push_back(entry("http://tracker.coppersurfer.tk/announce")); + al.push_back(entry("http://tracker.coppersurfer.tk:6969/announce")); + al.push_back(entry("http://tracker.cpleft.com:2710/announce")); + al.push_back(entry("http://tracker.istole.it/announce")); + al.push_back(entry("http://tracker.kamyu.net/announce")); + al.push_back(entry("http://tracker.novalayer.org:6969/announce")); + al.push_back(entry("http://tracker.torrent.to:2710/announce")); + al.push_back(entry("http://tracker.torrentbay.to:6969/announce")); + al.push_back(entry("udp://tracker.openbittorrent.com:80")); + al.push_back(entry("udp://tracker.publicbt.com:80")); + + std::vector buf; + bencode(std::back_inserter(buf), torrent); + buf.push_back('\0'); + printf("%s\n", &buf[0]); + error_code ec; + torrent_info ti(&buf[0], buf.size(), ec); + + TEST_EQUAL(al.size(), ti.trackers().size()); + + std::string magnet = make_magnet_uri(ti); + printf("%s len: %d\n", magnet.c_str(), int(magnet.size())); +} + +TORRENT_TEST(make_magnet_uri2) +{ + // make_magnet_uri + entry info; + info["pieces"] = "aaaaaaaaaaaaaaaaaaaa"; + info["name"] = "test"; + info["name.utf-8"] = "test"; + info["piece length"] = 16 * 1024; + info["length"] = 3245; + entry torrent; + torrent["info"] = info; + + torrent["url-list"] = "http://foo.com/bar"; + + std::vector buf; + bencode(std::back_inserter(buf), torrent); + buf.push_back('\0'); + printf("%s\n", &buf[0]); + error_code ec; + torrent_info ti(&buf[0], buf.size(), ec); + + std::string magnet = make_magnet_uri(ti); + printf("%s len: %d\n", magnet.c_str(), int(magnet.size())); + TEST_CHECK(magnet.find("&ws=http%3a%2f%2ffoo.com%2fbar") != std::string::npos); }