8000 [3.12] gh-122170: Handle ValueError raised by os.stat() in linecache … · python/cpython@2e37d67 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2e37d67

Browse files
[3.12] gh-122170: Handle ValueError raised by os.stat() in linecache (GH-122176) (GH-122349)
(cherry picked from commit 7a6d4cc) Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
1 parent a4449a1 commit 2e37d67

File tree

3 files changed

+37
-2
lines changed

3 files changed

+37
-2
lines changed

Lib/linecache.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def checkcache(filename=None):
7070
continue # no-op for files loaded via a __loader__
7171
try:
8000
7272
stat = os.stat(fullname)
73-
except OSError:
73+
except (OSError, ValueError):
7474
cache.pop(filename, None)
7575
continue
7676
if size != stat.st_size or mtime != stat.st_mtime:
@@ -128,10 +128,12 @@ def updatecache(filename, module_globals=None):
128128
try:
129129
stat = os.stat(fullname)
130130
break
131-
except OSError:
131+
except (OSError, ValueError):
132132
pass
133133
else:
134134
return []
135+
except ValueError: # may be raised by os.stat()
136+
return []
135137
try:
136138
with tokenize.open(fullname) as fp:
137139
lines = fp.readlines()

Lib/test/test_linecache.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,37 @@ def test_loader(self):
276276
self.assertEqual(linecache.getlines(filename, module_globals),
277277
['source for x.y.z\n'])
278278

279+
def test_invalid_names(self):
280+
for name, desc in [
281+
('\x00', 'NUL bytes filename'),
282+
(__file__ + '\x00', 'filename with embedded NUL bytes'),
283+
# A filename with surrogate codes. A UnicodeEncodeError is raised
284+
# by os.stat() upon querying, which is a subclass of ValueError.
285+
("\uD834\uDD1E.py", 'surrogate codes (MUSICAL SYMBOL G CLEF)'),
286+
# For POSIX platforms, an OSError will be raised but for Windows
287+
# platforms, a ValueError is raised due to the path_t converter.
288+
# See: https://github.com/python/cpython/issues/122170
289+
('a' * 1_000_000, 'very long filename'),
290+
]:
291+
with self.subTest(f'updatecache: {desc}'):
292+
linecache.clearcache()
293+
lines = linecache.updatecache(name)
294+
self.assertListEqual(lines, [])
295+
self.assertNotIn(name, linecache.cache)
296+
297+
# hack into the cache (it shouldn't be allowed
298+
# but we never know what people do...)
299+
for key, fullname in [(name, 'ok'), ('key', name), (name, name)]:
300+
with self.subTest(f'checkcache: {desc}',
301+
key=key, fullname=fullname):
302+
linecache.clearcache()
303+
linecache.cache[key] = (0, 1234, [], fullname)
304+
linecache.checkcache(key)
305+
self.assertNotIn(key, linecache.cache)
306+
307+
# just to be sure that we did not mess with cache
308+
linecache.clearcache()
309+
279310

280311
class LineCacheInvalidationTests(unittest.TestCase):
281312
def setUp(self):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Handle :exc:`ValueError`\s raised by :func:`os.stat` in :mod:`linecache`.
2+
Patch by Bénédikt Tran.

0 commit comments

Comments
 (0)
0