summaryrefslogtreecommitdiffstats
path: root/Lib/fnmatch.py
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2022-06-05 08:46:29 (GMT)
committerGitHub <noreply@github.com>2022-06-05 08:46:29 (GMT)
commit0902c3d8edf7ef67972dd95f6a21670f5d1a4251 (patch)
tree08f8bbf28918ffc2efda41dcf9d1586636586d9b /Lib/fnmatch.py
parent6f8367d3489eff07139bc908fdf666fc904ca445 (diff)
downloadcpython-0902c3d8edf7ef67972dd95f6a21670f5d1a4251.zip
cpython-0902c3d8edf7ef67972dd95f6a21670f5d1a4251.tar.gz
cpython-0902c3d8edf7ef67972dd95f6a21670f5d1a4251.tar.bz2
gh-89973: Fix re.error in the fnmatch module. (GH-93072)
Character ranges with upper bound less that lower bound (e.g. [c-a]) are now interpreted as empty ranges, for compatibility with other glob pattern implementations. Previously it was re.error.
Diffstat (limited to 'Lib/fnmatch.py')
-rw-r--r--Lib/fnmatch.py30
1 files changed, 23 insertions, 7 deletions
diff --git a/Lib/fnmatch.py b/Lib/fnmatch.py
index 0f5a41a..d5e296f 100644
--- a/Lib/fnmatch.py
+++ b/Lib/fnmatch.py
@@ -102,7 +102,7 @@ def translate(pat):
add('\\[')
else:
stuff = pat[i:j]
- if '--' not in stuff:
+ if '-' not in stuff:
stuff = stuff.replace('\\', r'\\')
else:
chunks = []
@@ -114,7 +114,16 @@ def translate(pat):
chunks.append(pat[i:k])
i = k+1
k = k+3
- chunks.append(pat[i:j])
+ chunk = pat[i:j]
+ if chunk:
+ chunks.append(chunk)
+ else:
+ chunks[-1] += '-'
+ # Remove empty ranges -- invalid in RE.
+ for k in range(len(chunks)-1, 0, -1):
+ if chunks[k-1][-1] > chunks[k][0]:
+ chunks[k-1] = chunks[k-1][:-1] + chunks[k][1:]
+ del chunks[k]
# Escape backslashes and hyphens for set difference (--).
# Hyphens that create ranges shouldn't be escaped.
stuff = '-'.join(s.replace('\\', r'\\').replace('-', r'\-')
@@ -122,11 +131,18 @@ def translate(pat):
# Escape set operations (&&, ~~ and ||).
stuff = re.sub(r'([&~|])', r'\\\1', stuff)
i = j+1
- if stuff[0] == '!':
- stuff = '^' + stuff[1:]
- elif stuff[0] in ('^', '['):
- stuff = '\\' + stuff
- add(f'[{stuff}]')
+ if not stuff:
+ # Empty range: never match.
+ add('(?!)')
+ elif stuff == '!':
+ # Negated empty range: match any character.
+ add('.')
+ else:
+ if stuff[0] == '!':
+ stuff = '^' + stuff[1:]
+ elif stuff[0] in ('^', '['):
+ stuff = '\\' + stuff
+ add(f'[{stuff}]')
else:
add(re.escape(c))
assert i == n