Skip to content

Commit

Permalink
Do not use the absolute path to cache wheel extensions. (#226)
Browse files Browse the repository at this point in the history
Wheel names can be long and paths to mounted wheels can be long.
Previously `util.path_to_cache_dir()` was unconditionally building
cache paths using the absolute path of the cache directory joined
with the absolute path to a wheel being mounted. This makes it very
easy to generate in huge paths that exceed the maximum path length
(MAX_PATH) on Windows machines without the
[registry change](https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=registry)
to support long paths.

A user-wide shared location for cached data is potentially easy enough
to poison with incorrect extensions, so using the absolute path of a
wheel being mounted to cache extensions doesn't seem to add any more
protection and results in very long hard to read paths that can exceed
Windows path limits in out of the box installations.

Fixes #224
  • Loading branch information
stewartmiles authored Oct 7, 2024
1 parent 6fbadf1 commit fac84c7
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 5 deletions.
8 changes: 4 additions & 4 deletions distlib/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,7 @@ def get_cache_base(suffix=None):
return os.path.join(result, suffix)


def path_to_cache_dir(path):
def path_to_cache_dir(path, use_abspath=True):
"""
Convert an absolute path to a directory name for use in a cache.
Expand All @@ -799,7 +799,7 @@ def path_to_cache_dir(path):
#. Any occurrence of ``os.sep`` is replaced with ``'--'``.
#. ``'.cache'`` is appended.
"""
d, p = os.path.splitdrive(os.path.abspath(path))
d, p = os.path.splitdrive(os.path.abspath(path) if use_abspath else path)
if d:
d = d.replace(':', '---')
p = p.replace(os.sep, '--')
Expand Down Expand Up @@ -981,11 +981,11 @@ def __init__(self, base):
logger.warning('Directory \'%s\' is not private', base)
self.base = os.path.abspath(os.path.normpath(base))

def prefix_to_dir(self, prefix):
def prefix_to_dir(self, prefix, use_abspath=True):
"""
Converts a resource prefix to a directory name in the cache.
"""
return path_to_cache_dir(prefix)
return path_to_cache_dir(prefix, use_abspath=use_abspath)

def clear(self):
"""
Expand Down
2 changes: 1 addition & 1 deletion distlib/wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,7 @@ def _get_extensions(self):
wf = wrapper(bf)
extensions = json.load(wf)
cache = self._get_dylib_cache()
prefix = cache.prefix_to_dir(pathname)
prefix = cache.prefix_to_dir(self.filename, use_abspath=False)
cache_base = os.path.join(cache.base, prefix)
if not os.path.isdir(cache_base):
os.makedirs(cache_base)
Expand Down
5 changes: 5 additions & 0 deletions tests/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ def test_cache_base(self):
@unittest.skipIf(os.name != 'posix', 'Test is only valid for POSIX')
def test_path_to_cache_dir_posix(self):
self.assertEqual(path_to_cache_dir('/home/user/some-file.zip'), '--home--user--some-file.zip.cache')
self.assertEqual(path_to_cache_dir('path/to/some-file.zip'),
os.path.splitext(path_to_cache_dir(os.path.dirname(HERE)))[0] +
'--path--to--some-file.zip.cache')
self.assertEqual(path_to_cache_dir('path/to/some-file.zip', use_abspath=False),
'path--to--some-file.zip.cache')

@unittest.skipIf(os.name != 'nt', 'Test is only valid for Windows')
def test_path_to_cache_dir_nt(self):
Expand Down

0 comments on commit fac84c7

Please sign in to comment.