diff --git a/libtransmission/torrent-metainfo.cc b/libtransmission/torrent-metainfo.cc index 41a4f394e..3e7af97c3 100644 --- a/libtransmission/torrent-metainfo.cc +++ b/libtransmission/torrent-metainfo.cc @@ -366,17 +366,16 @@ struct MetainfoHandler final : public tr::benc::BasicHandler } else if (pathIs(InfoKey, PiecesKey)) { - if (std::size(value) % sizeof(tr_sha1_digest_t) == 0) + static auto constexpr Sha1Len = std::tuple_size_v; + auto const len = std::size(value); + if (len % Sha1Len != 0U) { - auto const n = std::size(value) / sizeof(tr_sha1_digest_t); - tm_.pieces_.resize(n); - std::copy_n(std::data(value), std::size(value), reinterpret_cast(std::data(tm_.pieces_))); - } - else - { - context.error.set(EINVAL, fmt::format("invalid piece size: {}", std::size(value))); - unhandled = true; + context.error.set(EINVAL, fmt::format("invalid 'pieces' size: {}", len)); + return false; } + + tm_.pieces_.resize(len / Sha1Len); + std::copy_n(std::data(value), len, reinterpret_cast(std::data(tm_.pieces_))); } else if (pathStartsWith(PieceLayersKey)) { diff --git a/tests/libtransmission/assets/invalid-pieces-length.torrent b/tests/libtransmission/assets/invalid-pieces-length.torrent new file mode 100644 index 000000000..c6c1dee4c --- /dev/null +++ b/tests/libtransmission/assets/invalid-pieces-length.torrent @@ -0,0 +1 @@ +d8:announce28:https://example.com/announce8:checksum64:78d16df696e22610ab7c2e10a335a6b2543eaa8c10508a36b9760c69cdb3fb557:comment14:sample torrent10:created by13:uTorrent/204013:creation datei1317056433e8:encoding5:UTF-84:infod5:filesld6:lengthi8388608e4:pathl9:file1.txteed6:lengthi8388608e4:pathl9:file2.mkveed6:lengthi8388608e4:pathl9:file3.nfoeee4:name15:ThisIsMyTorrent12:piece lengthi4194304e6:pieces119:+ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªª7:privatei1e6:source15:Example Trackeree \ No newline at end of file diff --git a/tests/libtransmission/torrent-metainfo-test.cc b/tests/libtransmission/torrent-metainfo-test.cc index 5a4e8d4a4..20dfc30fb 100644 --- a/tests/libtransmission/torrent-metainfo-test.cc +++ b/tests/libtransmission/torrent-metainfo-test.cc @@ -207,10 +207,14 @@ TEST_F(TorrentMetainfoTest, GetRightStyleWebseedString) } // Test for https://github.com/transmission/transmission/issues/3591 -TEST_F(TorrentMetainfoTest, parseBencOOBWrite) +TEST_F(TorrentMetainfoTest, parseBencPiecesSize) { + auto const src_filename = tr_pathbuf{ LIBTRANSMISSION_TEST_ASSETS_DIR, "/invalid-pieces-length.torrent"sv }; + auto error = tr_error{}; auto tm = tr_torrent_metainfo{}; - EXPECT_FALSE(tm.parse_benc(tr_base64_decode("ZGg0OmluZm9kNjpwaWVjZXMzOkFpzQ=="))); + EXPECT_FALSE(tm.parse_torrent_file(src_filename, nullptr, &error)); + EXPECT_EQ(error.code(), EINVAL); + EXPECT_EQ(error.message(), "invalid 'pieces' size: 119"sv); } } // namespace tr::test