From 82160bfc95021ca39812038c50532e171b61cfd7 Mon Sep 17 00:00:00 2001 From: Alan McGovern Date: Wed, 26 Oct 2022 23:40:40 +0100 Subject: [PATCH] Files with no content should have no piece root. WHen checking the hash of piece 0, we should skip past files with a length of 0. This is important as if the file is smaller than PieceLength in size, the 'PieceRoot' of the file is used instead of the piece hashes, and so we need to ensure we pick the pieces root from the file which has the actual content. --- .../MonoTorrent/PieceHashesV2.cs | 3 ++- .../MonoTorrent/PieceHashesTests.cs | 20 ++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/MonoTorrent.Client/MonoTorrent/PieceHashesV2.cs b/src/MonoTorrent.Client/MonoTorrent/PieceHashesV2.cs index 624b78768..f43cf5c84 100644 --- a/src/MonoTorrent.Client/MonoTorrent/PieceHashesV2.cs +++ b/src/MonoTorrent.Client/MonoTorrent/PieceHashesV2.cs @@ -74,7 +74,8 @@ public ReadOnlyPieceHash GetHash (int hashIndex) throw new ArgumentOutOfRangeException (nameof (hashIndex), $"Value must be grater than or equal to '0' and less than '{Count}'"); for (int i = 0; i < Files.Count; i++) { - if (hashIndex < Files[i].StartPieceIndex || hashIndex > Files[i].EndPieceIndex) + // Empty files have no root hash, as they have no data. Skip them. + if (hashIndex < Files[i].StartPieceIndex || hashIndex > Files[i].EndPieceIndex || Files[i].Length == 0) continue; // If the file has 2 or more pieces then we'll need to grab the appropriate sha from the layer diff --git a/src/Tests/Tests.MonoTorrent.Client/MonoTorrent/PieceHashesTests.cs b/src/Tests/Tests.MonoTorrent.Client/MonoTorrent/PieceHashesTests.cs index ba7e1b0be..3549641a7 100644 --- a/src/Tests/Tests.MonoTorrent.Client/MonoTorrent/PieceHashesTests.cs +++ b/src/Tests/Tests.MonoTorrent.Client/MonoTorrent/PieceHashesTests.cs @@ -27,11 +27,14 @@ // +using System; using System.Linq; +using MonoTorrent.BEncoding; + using NUnit.Framework; -namespace MonoTorrent.Common +namespace MonoTorrent { [TestFixture] public class PieceHashesTests @@ -56,5 +59,20 @@ public void V2Only_NoHashes_Count () { Assert.AreEqual (0, new PieceHashes (null, null).Count); } + + [Test] + public void V2Only_WithEmptyFiles () + { + var files = new[] { + new TorrentFile("a", length: 0, startIndex: 0, endIndex: 0, 0, TorrentFileAttributes.None, 0), + new TorrentFile("b", length: 1, startIndex: 0, endIndex: 0, 0, new MerkleRoot(Enumerable.Repeat(1, 32).ToArray ()), TorrentFileAttributes.None, 0), + new TorrentFile("c", length: 2, startIndex: 1, endIndex: 1, 1, new MerkleRoot(Enumerable.Repeat(2, 32).ToArray ()), TorrentFileAttributes.None, 0), + }; + + var pieceHashesV2 = new PieceHashesV2 (Constants.BlockSize * 4, files, new BEncodedDictionary ()); + var hash = pieceHashesV2.GetHash (0); + Assert.IsTrue (files[1].PiecesRoot.AsMemory ().Span.SequenceEqual (hash.V2Hash.Span)); + Assert.IsTrue (hash.V1Hash.IsEmpty); + } } }