From f433f2ee17e27714b44f59be10f08e507ccb760d Mon Sep 17 00:00:00 2001 From: Jordan Lee Date: Mon, 9 Jun 2014 02:53:04 +0000 Subject: [PATCH] (trunk, libT) #5517 when parsing a torrent's metainfo's path list, allow empty components because some .torrent files innocently have them. Update unit tests. --- libtransmission/metainfo-test.c | 120 ++++++++++++++++++++++++-------- libtransmission/metainfo.c | 13 +++- libtransmission/variant-benc.c | 4 +- 3 files changed, 104 insertions(+), 33 deletions(-) diff --git a/libtransmission/metainfo-test.c b/libtransmission/metainfo-test.c index 02d2acd45..b5e44527b 100644 --- a/libtransmission/metainfo-test.c +++ b/libtransmission/metainfo-test.c @@ -7,40 +7,102 @@ * $Id$ */ -#include "transmission.h" - #include "libtransmission-test.h" +#include "transmission.h" + +#include + static int -test1 (void) +test_magnet_link (void) { - tr_info inf; - tr_ctor * ctor; - const char * magnet_link; - tr_parse_result parse_result; + tr_info inf; + tr_ctor * ctor; + const char * magnet_link; + tr_parse_result parse_result; - /* background info @ http://wiki.theory.org/BitTorrent_Magnet-URI_Webseeding */ - magnet_link = "magnet:?" - "xt=urn:btih:14FFE5DD23188FD5CB53A1D47F1289DB70ABF31E" - "&dn=ubuntu+12+04+1+desktop+32+bit" - "&tr=http%3A%2F%2Ftracker.publicbt.com%2Fannounce" - "&tr=udp%3A%2F%2Ftracker.publicbt.com%3A80" - "&ws=http://transmissionbt.com "; - ctor = tr_ctorNew (NULL); - tr_ctorSetMetainfoFromMagnetLink (ctor, magnet_link); - parse_result = tr_torrentParse (ctor, &inf); - check_int_eq (inf.fileCount, 0); /* cos it's a magnet link */ - check_int_eq (parse_result, TR_PARSE_OK); - check_int_eq (inf.trackerCount, 2); - check_streq ("http://tracker.publicbt.com/announce", inf.trackers[0].announce); - check_streq ("udp://tracker.publicbt.com:80", inf.trackers[1].announce); - check_int_eq (inf.webseedCount, 1); - check_streq ("http://transmissionbt.com", inf.webseeds[0]); + /* background info @ http://wiki.theory.org/BitTorrent_Magnet-URI_Webseeding */ + magnet_link = "magnet:?" + "xt=urn:btih:14FFE5DD23188FD5CB53A1D47F1289DB70ABF31E" + "&dn=ubuntu+12+04+1+desktop+32+bit" + "&tr=http%3A%2F%2Ftracker.publicbt.com%2Fannounce" + "&tr=udp%3A%2F%2Ftracker.publicbt.com%3A80" + "&ws=http://transmissionbt.com "; + ctor = tr_ctorNew (NULL); + tr_ctorSetMetainfoFromMagnetLink (ctor, magnet_link); + parse_result = tr_torrentParse (ctor, &inf); + check_int_eq (inf.fileCount, 0); /* cos it's a magnet link */ + check_int_eq (parse_result, TR_PARSE_OK); + check_int_eq (inf.trackerCount, 2); + check_streq ("http://tracker.publicbt.com/announce", inf.trackers[0].announce); + check_streq ("udp://tracker.publicbt.com:80", inf.trackers[1].announce); + check_int_eq (inf.webseedCount, 1); + check_streq ("http://transmissionbt.com", inf.webseeds[0]); - /* cleanup */ - tr_metainfoFree (&inf); - tr_ctorFree (ctor); - return 0; + /* cleanup */ + tr_metainfoFree (&inf); + tr_ctorFree (ctor); + return 0; +} + +#define BEFORE_PATH "d10:created by25:Transmission/2.82 (14160)13:creation datei1402280218e8:encoding5:UTF-84:infod5:filesld6:lengthi2e4:pathl" +#define AFTER_PATH "eed6:lengthi2e4:pathl5:b.txteee4:name3:foo12:piece lengthi32768e6:pieces20:ÞÉ`âM‘‹Šs¡Å;˺¬.åÂà7:privatei0eee" + +static int +test_metainfo (void) +{ + size_t i; + const struct { + int expected_benc_err; + int expected_parse_result; + const void * benc; + } metainfo[] = { + { 0, TR_PARSE_OK, BEFORE_PATH "5:a.txt" AFTER_PATH }, + + /* allow empty components, but not =all= empty components, see bug #5517 */ + { 0, TR_PARSE_OK, BEFORE_PATH "0:5:a.txt" AFTER_PATH }, + { 0, TR_PARSE_ERR, BEFORE_PATH "0:0:" AFTER_PATH }, + + /* don't allow path components in a filename */ + { 0, TR_PARSE_ERR, BEFORE_PATH "7:a/a.txt" AFTER_PATH }, + + /* fail on "." components */ + { 0, TR_PARSE_ERR, BEFORE_PATH "1:.5:a.txt" AFTER_PATH }, + { 0, TR_PARSE_ERR, BEFORE_PATH "5:a.txt1:." AFTER_PATH }, + + /* fail on ".." components */ + { 0, TR_PARSE_ERR, BEFORE_PATH "2:..5:a.txt" AFTER_PATH }, + { 0, TR_PARSE_ERR, BEFORE_PATH "5:a.txt2:.." AFTER_PATH }, + + /* fail on empty string */ + { EILSEQ, TR_PARSE_ERR, "" } + }; + + tr_logSetLevel(0); /* yes, we already know these will generate errors, thank you... */ + + + for (i=0; i<(sizeof(metainfo) / sizeof(metainfo[0])); i++) + { + tr_ctor * ctor = tr_ctorNew (NULL); + const int err = tr_ctorSetMetainfo (ctor, metainfo[i].benc, strlen(metainfo[i].benc)); + check_int_eq (metainfo[i].expected_benc_err, err); + if (!err) + { + const tr_parse_result parse_result = tr_torrentParse (ctor, NULL); + check_int_eq (metainfo[i].expected_parse_result, parse_result); + } + tr_ctorFree (ctor); + } + + return 0; +} + +int +main (void) +{ + const testFunc tests[] = { test_magnet_link, + test_metainfo }; + + return runTests (tests, NUM_TESTS (tests)); } -MAIN_SINGLE_TEST (test1) diff --git a/libtransmission/metainfo.c b/libtransmission/metainfo.c index 2f99cfe26..2957a937b 100644 --- a/libtransmission/metainfo.c +++ b/libtransmission/metainfo.c @@ -76,7 +76,6 @@ static bool path_component_is_suspicious (const char * component) { return (component == NULL) - || (*component == '\0') || (strpbrk (component, PATH_DELIMITER_CHARS) != NULL) || (strcmp (component, ".") == 0) || (strcmp (component, "..") == 0); @@ -86,6 +85,7 @@ static bool getfile (char ** setme, const char * root, tr_variant * path, struct evbuffer * buf) { bool success = false; + size_t root_len = 0; *setme = NULL; @@ -99,7 +99,8 @@ getfile (char ** setme, const char * root, tr_variant * path, struct evbuffer * success = true; evbuffer_drain (buf, evbuffer_get_length (buf)); - evbuffer_add (buf, root, strlen (root)); + root_len = strlen (root); + evbuffer_add (buf, root, root_len); for (i=0; itype || !tr_ptrArrayEmpty(&stack); + if (!err && (!top->type || !tr_ptrArrayEmpty(&stack))) + err = EILSEQ; if (!err && setme_end) *setme_end = (const char*) buf;