Merge pull request #1493 from jodal/fix/1345-file-crashes-on-non-ascii-media-dir

file: Fix crash when media_dirs contains non-ASCII chars
This commit is contained in:
Thomas Adamcik 2016-03-26 20:24:22 +01:00
commit 5e640979f4
4 changed files with 37 additions and 1 deletions

View File

@ -34,6 +34,10 @@ Bug fix release.
- Core: Avoid endless loop if all tracks in the tracklist are unplayable and - Core: Avoid endless loop if all tracks in the tracklist are unplayable and
consume mode is off. (Fixes: :issue:`1221`, :issue:`1454`, PR: :issue:`1455`) consume mode is off. (Fixes: :issue:`1221`, :issue:`1454`, PR: :issue:`1455`)
- File: Ensure path comparision is done between bytestrings only. Fixes crash
where a :confval:`file/media_dirs` path contained non-ASCII characters.
(Fixes: :issue:`1345`, PR: :issue:`1493`)
v2.0.0 (2016-02-15) v2.0.0 (2016-02-15)
=================== ===================

View File

@ -132,5 +132,6 @@ class FileLibraryProvider(backend.LibraryProvider):
def _is_in_basedir(self, local_path): def _is_in_basedir(self, local_path):
return any( return any(
path.is_path_inside_base_dir(local_path, media_dir['path']) path.is_path_inside_base_dir(
local_path, media_dir['path'].encode('utf-8'))
for media_dir in self._media_dirs) for media_dir in self._media_dirs)

View File

@ -196,6 +196,11 @@ def find_mtimes(root, follow=False):
def is_path_inside_base_dir(path, base_path): def is_path_inside_base_dir(path, base_path):
if not isinstance(path, bytes):
raise ValueError('path is not a bytestring')
if not isinstance(base_path, bytes):
raise ValueError('base_path is not a bytestring')
if path.endswith(os.sep): if path.endswith(os.sep):
raise ValueError('Path %s cannot end with a path separator' raise ValueError('Path %s cannot end with a path separator'
% path) % path)

View File

@ -7,6 +7,8 @@ import shutil
import tempfile import tempfile
import unittest import unittest
import pytest
from mopidy import compat, exceptions from mopidy import compat, exceptions
from mopidy.internal import path from mopidy.internal import path
from mopidy.internal.gi import GLib from mopidy.internal.gi import GLib
@ -392,6 +394,30 @@ class FindMTimesTest(unittest.TestCase):
self.assertEqual(errors, {}) self.assertEqual(errors, {})
class TestIsPathInsideBaseDir(object):
def test_when_inside(self):
assert path.is_path_inside_base_dir(
'/æ/øå'.encode('utf-8'),
''.encode('utf-8'))
def test_when_outside(self):
assert not path.is_path_inside_base_dir(
'/æ/øå'.encode('utf-8'),
''.encode('utf-8'))
def test_byte_inside_str_fails(self):
with pytest.raises(ValueError):
path.is_path_inside_base_dir('/æ/øå'.encode('utf-8'), '')
def test_str_inside_byte_fails(self):
with pytest.raises(ValueError):
path.is_path_inside_base_dir('/æ/øå', ''.encode('utf-8'))
def test_str_inside_str_fails(self):
with pytest.raises(ValueError):
path.is_path_inside_base_dir('/æ/øå', '')
# TODO: kill this in favour of just os.path.getmtime + mocks # TODO: kill this in favour of just os.path.getmtime + mocks
class MtimeTest(unittest.TestCase): class MtimeTest(unittest.TestCase):