]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Correctly hash hybrid torrents with trailing v1 padding file v1.56.1
authorMatt Joiner <anacrolix@gmail.com>
Tue, 11 Jun 2024 06:21:04 +0000 (16:21 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Tue, 11 Jun 2024 06:21:24 +0000 (16:21 +1000)
Fixes #949.

issue-949_test.go [new file with mode: 0644]
metainfo/info.go
metainfo/piece.go
testdata/issue-949.torrent [new file with mode: 0644]
torrent.go

diff --git a/issue-949_test.go b/issue-949_test.go
new file mode 100644 (file)
index 0000000..f04bd55
--- /dev/null
@@ -0,0 +1,27 @@
+package torrent
+
+import (
+       "github.com/anacrolix/torrent/metainfo"
+       qt "github.com/frankban/quicktest"
+       "testing"
+)
+
+func TestIssue949LastPieceZeroPadding(t *testing.T) {
+       // This torrent has a padding file after the last file listed in the v2 info file tree.
+       mi, err := metainfo.LoadFromFile("testdata/issue-949.torrent")
+       if err != nil {
+               panic(err)
+       }
+       info, err := mi.UnmarshalInfo()
+       if err != nil {
+               panic(err)
+       }
+       lastPiece := info.Piece(info.NumPieces() - 1)
+       c := qt.New(t)
+       c.Assert(info.FilesArePieceAligned(), qt.IsTrue)
+       // Check the v1 piece length includes the trailing padding file.
+       c.Check(lastPiece.V1Length(), qt.Equals, info.PieceLength)
+       // The v2 piece should only include the file data, which fits inside the piece length for this
+       // file.
+       c.Check(lastPiece.Length(), qt.Equals, int64(3677645))
+}
index 3f14b08b5b97ee697a0056daa9caaa6333595b30..5252e209f78db67fe77c1a19b892275ea3ea3e39 100644 (file)
@@ -150,9 +150,8 @@ func (info *Info) IsDir() bool {
        return len(info.Files) != 0
 }
 
-// The files field, converted up from the old single-file in the parent info
-// dict if necessary. This is a helper to avoid having to conditionally handle
-// single and multi-file torrent infos.
+// The files field, converted up from the old single-file in the parent info dict if necessary. This
+// is a helper to avoid having to conditionally handle single and multi-file torrent infos.
 func (info *Info) UpvertedFiles() (files []FileInfo) {
        if info.HasV2() {
                info.FileTree.upvertedFiles(info.PieceLength, func(fi FileInfo) {
@@ -160,6 +159,12 @@ func (info *Info) UpvertedFiles() (files []FileInfo) {
                })
                return
        }
+       return info.UpvertedV1Files()
+}
+
+// UpvertedFiles but specific to the files listed in the v1 info fields. This will include padding
+// files for example that wouldn't appear in v2 file trees.
+func (info *Info) UpvertedV1Files() (files []FileInfo) {
        if len(info.Files) == 0 {
                return []FileInfo{{
                        Length: info.Length,
index c4101a6dc63b7d1566c68bb894a73497b9bc07fd..946e874bb248d75504d5fba1b1e5c22e924e0274 100644 (file)
@@ -45,7 +45,7 @@ func (p Piece) V1Length() int64 {
        case 0 <= i && i < lastPiece:
                return p.Info.PieceLength
        case lastPiece >= 0 && i == lastPiece:
-               files := p.Info.UpvertedFiles()
+               files := p.Info.UpvertedV1Files()
                lastFile := files[len(files)-1]
                length := lastFile.TorrentOffset + lastFile.Length - int64(i)*p.Info.PieceLength
                if length <= 0 || length > p.Info.PieceLength {
diff --git a/testdata/issue-949.torrent b/testdata/issue-949.torrent
new file mode 100644 (file)
index 0000000..7ebf67d
Binary files /dev/null and b/testdata/issue-949.torrent differ
index 3a5d358c6c05f9360ee5a95854b59a1e036946df..26c1714d2df73f05457a1670e2cf4341b2588f4e 100644 (file)
@@ -1157,8 +1157,8 @@ func (t *Torrent) hashPiece(piece pieceIndex) (
                }
                h := pieceHash.New()
                differingPeers, err = t.hashPieceWithSpecificHash(piece, h)
-               // For a hybrid torrent, we work with the v2 files, but if we use a v1 hash, we can assume that
-               // the pieces are padded with zeroes.
+               // For a hybrid torrent, we work with the v2 files, but if we use a v1 hash, we can assume
+               // that the pieces are padded with zeroes.
                if t.info.FilesArePieceAligned() {
                        paddingLen := p.Info().V1Length() - p.Info().Length()
                        written, err := io.CopyN(h, zeroReader, paddingLen)