diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2022-06-05 08:46:29 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-05 08:46:29 (GMT) |
commit | 0902c3d8edf7ef67972dd95f6a21670f5d1a4251 (patch) | |
tree | 08f8bbf28918ffc2efda41dcf9d1586636586d9b /Lib/fnmatch.py | |
parent | 6f8367d3489eff07139bc908fdf666fc904ca445 (diff) | |
download | cpython-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.py | 30 |
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 |