(trunk, libT) #5517 'Don't create or add torrents with "../" at the beginning of the path or "/../" anywhere in the path' -- fixed.
This commit is contained in:
parent
4097f6333a
commit
8f5c7809e7
|
@ -30,6 +30,19 @@
|
|||
****
|
||||
***/
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#define PATH_DELIMITER_CHARS "/\\"
|
||||
#else
|
||||
#define PATH_DELIMITER_CHARS "/"
|
||||
#endif
|
||||
|
||||
static inline bool
|
||||
char_is_path_separator (char c)
|
||||
{
|
||||
return strchr(PATH_DELIMITER_CHARS, c) != NULL;
|
||||
}
|
||||
|
||||
char*
|
||||
tr_metainfoGetBasename (const tr_info * inf)
|
||||
{
|
||||
|
@ -39,7 +52,7 @@ tr_metainfoGetBasename (const tr_info * inf)
|
|||
char * ret = tr_strdup_printf ("%s.%16.16s", name, inf->hashString);
|
||||
|
||||
for (i=0; i<name_len; ++i)
|
||||
if (ret[i] == '/')
|
||||
if (char_is_path_separator (ret[i]))
|
||||
ret[i] = '_';
|
||||
|
||||
return ret;
|
||||
|
@ -60,11 +73,13 @@ getTorrentFilename (const tr_session * session, const tr_info * inf)
|
|||
***/
|
||||
|
||||
static bool
|
||||
path_is_suspicious (const char * path)
|
||||
path_component_is_suspicious (const char * component)
|
||||
{
|
||||
return (path == NULL)
|
||||
|| (!strncmp (path, "../", 3))
|
||||
|| (strstr (path, "/../") != NULL);
|
||||
return (component == NULL)
|
||||
|| (*component == '\0')
|
||||
|| (strpbrk (component, PATH_DELIMITER_CHARS) != NULL)
|
||||
|| (strcmp (component, ".") == 0)
|
||||
|| (strcmp (component, "..") == 0);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -72,35 +87,41 @@ getfile (char ** setme, const char * root, tr_variant * path, struct evbuffer *
|
|||
{
|
||||
bool success = false;
|
||||
|
||||
*setme = NULL;
|
||||
|
||||
/* root's already been checked by caller */
|
||||
assert (!path_component_is_suspicious (root));
|
||||
|
||||
if (tr_variantIsList (path))
|
||||
{
|
||||
int i;
|
||||
const int n = tr_variantListSize (path);
|
||||
|
||||
success = true;
|
||||
evbuffer_drain (buf, evbuffer_get_length (buf));
|
||||
evbuffer_add (buf, root, strlen (root));
|
||||
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
size_t len;
|
||||
const char * str;
|
||||
|
||||
if (tr_variantGetStr (tr_variantListChild (path, i), &str, &len))
|
||||
if (!tr_variantGetStr (tr_variantListChild (path, i), &str, &len) ||
|
||||
path_component_is_suspicious (str))
|
||||
{
|
||||
evbuffer_add (buf, TR_PATH_DELIMITER_STR, 1);
|
||||
evbuffer_add (buf, str, len);
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*setme = tr_utf8clean ((char*)evbuffer_pullup (buf, -1), evbuffer_get_length (buf));
|
||||
/* fprintf (stderr, "[%s]\n", *setme); */
|
||||
success = true;
|
||||
evbuffer_add (buf, TR_PATH_DELIMITER_STR, 1);
|
||||
evbuffer_add (buf, str, len);
|
||||
}
|
||||
}
|
||||
|
||||
if ((*setme != NULL) && path_is_suspicious (*setme))
|
||||
if (success)
|
||||
{
|
||||
tr_free (*setme);
|
||||
*setme = NULL;
|
||||
success = false;
|
||||
*setme = tr_utf8clean ((char*)evbuffer_pullup (buf, -1), evbuffer_get_length (buf));
|
||||
/*fprintf (stderr, "[%s]\n", *setme);*/
|
||||
}
|
||||
|
||||
return success;
|
||||
|
@ -116,7 +137,14 @@ parseFiles (tr_info * inf, tr_variant * files, const tr_variant * length)
|
|||
if (tr_variantIsList (files)) /* multi-file mode */
|
||||
{
|
||||
tr_file_index_t i;
|
||||
struct evbuffer * buf = evbuffer_new ();
|
||||
struct evbuffer * buf;
|
||||
const char * result;
|
||||
|
||||
if (path_component_is_suspicious (inf->name))
|
||||
return "path";
|
||||
|
||||
buf = evbuffer_new ();
|
||||
result = NULL;
|
||||
|
||||
inf->isMultifile = 1;
|
||||
inf->fileCount = tr_variantListSize (files);
|
||||
|
@ -129,27 +157,40 @@ parseFiles (tr_info * inf, tr_variant * files, const tr_variant * length)
|
|||
|
||||
file = tr_variantListChild (files, i);
|
||||
if (!tr_variantIsDict (file))
|
||||
return "files";
|
||||
{
|
||||
result = "files";
|
||||
break;
|
||||
}
|
||||
|
||||
if (!tr_variantDictFindList (file, TR_KEY_path_utf_8, &path))
|
||||
if (!tr_variantDictFindList (file, TR_KEY_path, &path))
|
||||
return "path";
|
||||
{
|
||||
result = "path";
|
||||
break;
|
||||
}
|
||||
|
||||
if (!getfile (&inf->files[i].name, inf->name, path, buf))
|
||||
return "path";
|
||||
{
|
||||
result = "path";
|
||||
break;
|
||||
}
|
||||
|
||||
if (!tr_variantDictFindInt (file, TR_KEY_length, &len))
|
||||
return "length";
|
||||
{
|
||||
result = "length";
|
||||
break;
|
||||
}
|
||||
|
||||
inf->files[i].length = len;
|
||||
inf->totalSize += len;
|
||||
}
|
||||
|
||||
evbuffer_free (buf);
|
||||
return result;
|
||||
}
|
||||
else if (tr_variantGetInt (length, &len)) /* single-file mode */
|
||||
{
|
||||
if (path_is_suspicious (inf->name))
|
||||
if (path_component_is_suspicious (inf->name))
|
||||
return "path";
|
||||
|
||||
inf->isMultifile = 0;
|
||||
|
|
Loading…
Reference in New Issue