]> granicus.if.org Git - transmission/commitdiff
(trunk, libT) #5517 when parsing a torrent's metainfo's path list, allow empty compon...
authorJordan Lee <jordan@transmissionbt.com>
Mon, 9 Jun 2014 02:53:04 +0000 (02:53 +0000)
committerJordan Lee <jordan@transmissionbt.com>
Mon, 9 Jun 2014 02:53:04 +0000 (02:53 +0000)
libtransmission/metainfo-test.c
libtransmission/metainfo.c
libtransmission/variant-benc.c

index 02d2acd4572cdc45ee441ccffedb2936e7717e27..b5e44527bd3117f4356901fa32acea4a2a1ce229 100644 (file)
  * $Id$
  */
 
+#include "libtransmission-test.h"
+
 #include "transmission.h"
 
-#include "libtransmission-test.h"
+#include <errno.h>
 
 static int
-test1 (void)
+test_magnet_link (void)
+{
+  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]);
+
+  /* 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:\ 5ÞÉ`âM\91\8b\8as¡Å;˺¬.åÂà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)
 {
-    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]);
-
-    /* cleanup */
-    tr_metainfoFree (&inf);
-    tr_ctorFree (ctor);
-    return 0;
+  const testFunc tests[] = { test_magnet_link,
+                             test_metainfo };
+
+  return runTests (tests, NUM_TESTS (tests));
 }
 
-MAIN_SINGLE_TEST (test1)
index 2f99cfe26fe7e91a9dabaf21fac2301e2bcf9391..2957a937bd9707ff1b18830a849a35cf8b84fc6a 100644 (file)
@@ -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; i<n; i++)
         {
@@ -113,11 +114,19 @@ getfile (char ** setme, const char * root, tr_variant * path, struct evbuffer *
               break;
             }
 
+          if (!*str)
+            continue;
+
           evbuffer_add (buf, TR_PATH_DELIMITER_STR, 1);
           evbuffer_add (buf, str, len);
         }
     }
 
+  if (success && (evbuffer_get_length (buf) <= root_len))
+    {
+      success = false;
+    }
+
   if (success)
     {
       *setme = tr_utf8clean ((char*)evbuffer_pullup (buf, -1), evbuffer_get_length (buf));
index c3b0aa70b8e14fcef1b6efac5e6030aa71233875..02a391d84fa53fd9858110a54bd846eaa713e39d 100644 (file)
@@ -248,8 +248,8 @@ tr_variantParseBenc (const void    * buf_in,
         break;
     }
 
-  if (!err)
-    err = !top->type || !tr_ptrArrayEmpty(&stack);
+  if (!err && (!top->type || !tr_ptrArrayEmpty(&stack)))
+    err = EILSEQ;
 
   if (!err && setme_end)
     *setme_end = (const char*) buf;