Changeset 14264


Ignore:
Timestamp:
Apr 27, 2014, 8:17:16 PM (9 years ago)
Author:
jordan
Message:

(trunk, libT) #5517 'Don't create or add torrents with "../" at the beginning of the path or "/../" anywhere in the path' -- fixed.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/metainfo.c

    r14241 r14264  
    3131***/
    3232
     33
     34#ifdef WIN32
     35  #define PATH_DELIMITER_CHARS "/\\"
     36#else
     37  #define PATH_DELIMITER_CHARS "/"
     38#endif
     39
     40static inline bool
     41char_is_path_separator (char c)
     42{
     43  return strchr(PATH_DELIMITER_CHARS, c) != NULL;
     44}
     45
    3346char*
    3447tr_metainfoGetBasename (const tr_info * inf)
     
    4053
    4154  for (i=0; i<name_len; ++i)
    42     if (ret[i] == '/')
     55    if (char_is_path_separator (ret[i]))
    4356      ret[i] = '_';
    4457
     
    6174
    6275static bool
    63 path_is_suspicious (const char * path)
    64 {
    65   return (path == NULL)
    66       || (!strncmp (path, "../", 3))
    67       || (strstr (path, "/../") != NULL);
     76path_component_is_suspicious (const char * component)
     77{
     78  return (component == NULL)
     79      || (*component == '\0')
     80      || (strpbrk (component, PATH_DELIMITER_CHARS) != NULL)
     81      || (strcmp (component, ".") == 0)
     82      || (strcmp (component, "..") == 0);
    6883}
    6984
     
    7388  bool success = false;
    7489
     90  *setme = NULL;
     91
     92  /* root's already been checked by caller */
     93  assert (!path_component_is_suspicious (root));
     94
    7595  if (tr_variantIsList (path))
    7696    {
     
    7898      const int n = tr_variantListSize (path);
    7999
     100      success = true;
    80101      evbuffer_drain (buf, evbuffer_get_length (buf));
    81102      evbuffer_add (buf, root, strlen (root));
     103
    82104      for (i=0; i<n; i++)
    83105        {
     
    85107          const char * str;
    86108
    87           if (tr_variantGetStr (tr_variantListChild (path, i), &str, &len))
     109          if (!tr_variantGetStr (tr_variantListChild (path, i), &str, &len) ||
     110              path_component_is_suspicious (str))
    88111            {
    89               evbuffer_add (buf, TR_PATH_DELIMITER_STR, 1);
    90               evbuffer_add (buf, str, len);
     112              success = false;
     113              break;
    91114            }
    92         }
    93 
     115
     116          evbuffer_add (buf, TR_PATH_DELIMITER_STR, 1);
     117          evbuffer_add (buf, str, len);
     118        }
     119    }
     120
     121  if (success)
     122    {
    94123      *setme = tr_utf8clean ((char*)evbuffer_pullup (buf, -1), evbuffer_get_length (buf));
    95       /* fprintf (stderr, "[%s]\n", *setme); */
    96       success = true;
    97     }
    98 
    99   if ((*setme != NULL) && path_is_suspicious (*setme))
    100     {
    101       tr_free (*setme);
    102       *setme = NULL;
    103       success = false;
     124      /*fprintf (stderr, "[%s]\n", *setme);*/
    104125    }
    105126
     
    117138    {
    118139      tr_file_index_t i;
    119       struct evbuffer * buf = evbuffer_new ();
     140      struct evbuffer * buf;
     141      const char * result;
     142
     143      if (path_component_is_suspicious (inf->name))
     144        return "path";
     145
     146      buf = evbuffer_new ();
     147      result = NULL;
    120148
    121149      inf->isMultifile = 1;
     
    130158          file = tr_variantListChild (files, i);
    131159          if (!tr_variantIsDict (file))
    132             return "files";
     160            {
     161              result = "files";
     162              break;
     163            }
    133164
    134165          if (!tr_variantDictFindList (file, TR_KEY_path_utf_8, &path))
    135166            if (!tr_variantDictFindList (file, TR_KEY_path, &path))
    136               return "path";
     167              {
     168                result = "path";
     169                break;
     170              }
    137171
    138172          if (!getfile (&inf->files[i].name, inf->name, path, buf))
    139             return "path";
     173            {
     174              result = "path";
     175              break;
     176            }
    140177
    141178          if (!tr_variantDictFindInt (file, TR_KEY_length, &len))
    142             return "length";
     179            {
     180              result = "length";
     181              break;
     182            }
    143183
    144184          inf->files[i].length = len;
     
    147187
    148188      evbuffer_free (buf);
     189      return result;
    149190    }
    150191  else if (tr_variantGetInt (length, &len)) /* single-file mode */
    151192    {
    152       if (path_is_suspicious (inf->name))
     193      if (path_component_is_suspicious (inf->name))
    153194        return "path";
    154195
Note: See TracChangeset for help on using the changeset viewer.