diff --git a/src/main/java/com/mykola2312/retracker/bencode/BTree.java b/src/main/java/com/mykola2312/retracker/bencode/BTree.java index 71937bf..edc8d0f 100644 --- a/src/main/java/com/mykola2312/retracker/bencode/BTree.java +++ b/src/main/java/com/mykola2312/retracker/bencode/BTree.java @@ -98,6 +98,8 @@ public class BTree { // advance past terminator offset++; return dict; + } else if (type == BDecoder.BE_END) { + throw new BDecodeMalformed(data, offset, "encountered terminator where it shouldn't be"); } else { // string // since string does not have leading type byte, move back offset offset--; diff --git a/src/test/java/com/mykola2312/retracker/bencode/BTreeTest.java b/src/test/java/com/mykola2312/retracker/bencode/BTreeTest.java index 721493e..910d05b 100644 --- a/src/test/java/com/mykola2312/retracker/bencode/BTreeTest.java +++ b/src/test/java/com/mykola2312/retracker/bencode/BTreeTest.java @@ -5,10 +5,15 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + import org.junit.jupiter.api.Test; import com.mykola2312.retracker.bencode.error.BDecodeError; import com.mykola2312.retracker.bencode.error.BDecodeMalformed; +import com.mykola2312.retracker.bencode.error.BError; public class BTreeTest { @Test @@ -116,4 +121,46 @@ public class BTreeTest { assertEquals(new BInteger(69), root.get(BType.INTEGER, "second")); }); } + + @Test + public void testNestedDict() throws BError { + final byte[] data = "d5:firstd6:secondd5:thirdi1337eeee".getBytes(); + + BTree tree = new BTree(); + assertDoesNotThrow(() -> { + tree.decode(data); + + BInteger value = tree + .asDict() + .get(BType.DICT, "first") + .get(BType.DICT, "second") + .get(BType.INTEGER, "third"); + assertNotNull(value); + assertEquals(new BInteger(1337), value); + }); + } + + @Test + public void testTorrentFile() throws BError, IOException { + final byte[] data = Files.readAllBytes(Path.of("test", "test.torrent")); + + BTree torrent = new BTree(); + assertDoesNotThrow(() -> { + torrent.decode(data); + + BDict root = torrent.asDict(); + assertEquals(new BString("http://example.com/announce"), root.get(BType.STRING, "announce")); + assertEquals(new BString("Test Comment"), root.get(BType.STRING, "comment")); + assertEquals(new BString("qBittorrent v4.6.5"), root.get(BType.STRING, "created by")); + assertEquals(new BInteger(1729033917), root.get(BType.INTEGER, "creation date")); + + BInteger pieceLength = root + .get(BType.DICT, "info") + .get(BType.DICT, "file tree") + .get(BType.DICT, "random-data.bin") + .get(BType.DICT, "") + .get(BType.INTEGER, "length"); + assertEquals(new BInteger(16777216), pieceLength); + }); + } } diff --git a/test/test.torrent b/test/test.torrent new file mode 100644 index 0000000..a3e53f4 Binary files /dev/null and b/test/test.torrent differ