mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
gh-136065: Fix quadratic complexity in os.path.expandvars() (GH-134952)
Co-authored-by: Łukasz Langa <lukasz@langa.pl>
This commit is contained in:
parent
81cec22a9b
commit
f029e8db62
5 changed files with 96 additions and 116 deletions
|
|
@ -285,42 +285,41 @@ def expanduser(path):
|
|||
# This expands the forms $variable and ${variable} only.
|
||||
# Non-existent variables are left unchanged.
|
||||
|
||||
_varprog = None
|
||||
_varprogb = None
|
||||
_varpattern = r'\$(\w+|\{[^}]*\}?)'
|
||||
_varsub = None
|
||||
_varsubb = None
|
||||
|
||||
def expandvars(path):
|
||||
"""Expand shell variables of form $var and ${var}. Unknown variables
|
||||
are left unchanged."""
|
||||
path = os.fspath(path)
|
||||
global _varprog, _varprogb
|
||||
global _varsub, _varsubb
|
||||
if isinstance(path, bytes):
|
||||
if b'$' not in path:
|
||||
return path
|
||||
if not _varprogb:
|
||||
if not _varsubb:
|
||||
import re
|
||||
_varprogb = re.compile(br'\$(\w+|\{[^}]*\})', re.ASCII)
|
||||
search = _varprogb.search
|
||||
_varsubb = re.compile(_varpattern.encode(), re.ASCII).sub
|
||||
sub = _varsubb
|
||||
start = b'{'
|
||||
end = b'}'
|
||||
environ = getattr(os, 'environb', None)
|
||||
else:
|
||||
if '$' not in path:
|
||||
return path
|
||||
if not _varprog:
|
||||
if not _varsub:
|
||||
import re
|
||||
_varprog = re.compile(r'\$(\w+|\{[^}]*\})', re.ASCII)
|
||||
search = _varprog.search
|
||||
_varsub = re.compile(_varpattern, re.ASCII).sub
|
||||
sub = _varsub
|
||||
start = '{'
|
||||
end = '}'
|
||||
environ = os.environ
|
||||
i = 0
|
||||
while True:
|
||||
m = search(path, i)
|
||||
if not m:
|
||||
break
|
||||
i, j = m.span(0)
|
||||
name = m.group(1)
|
||||
if name.startswith(start) and name.endswith(end):
|
||||
|
||||
def repl(m):
|
||||
name = m[1]
|
||||
if name.startswith(start):
|
||||
if not name.endswith(end):
|
||||
return m[0]
|
||||
name = name[1:-1]
|
||||
try:
|
||||
if environ is None:
|
||||
|
|
@ -328,13 +327,11 @@ def expandvars(path):
|
|||
else:
|
||||
value = environ[name]
|
||||
except KeyError:
|
||||
i = j
|
||||
return m[0]
|
||||
else:
|
||||
tail = path[j:]
|
||||
path = path[:i] + value
|
||||
i = len(path)
|
||||
path += tail
|
||||
return path
|
||||
return value
|
||||
|
||||
return sub(repl, path)
|
||||
|
||||
|
||||
# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue