Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7a6d4cc

Browse filesBrowse files
authored
gh-122170: Handle ValueError raised by os.stat() in linecache (GH-122176)
1 parent 8ac5565 commit 7a6d4cc
Copy full SHA for 7a6d4cc

File tree

Expand file treeCollapse file tree

3 files changed

+37
-2
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+37
-2
lines changed

‎Lib/linecache.py

Copy file name to clipboardExpand all lines: Lib/linecache.py
+4-2Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def checkcache(filename=None):
7070
return
7171
try:
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:
@@ -135,10 +135,12 @@ def updatecache(filename, module_globals=None):
135135
try:
136136
stat = os.stat(fullname)
137137
break
138-
except OSError:
138+
except (OSError, ValueError):
139139
pass
140140
else:
141141
return []
142+
except ValueError: # may be raised by os.stat()
143+
return []
142144
try:
143145
with tokenize.open(fullname) as fp:
144146
lines = fp.readlines()

‎Lib/test/test_linecache.py

Copy file name to clipboardExpand all lines: Lib/test/test_linecache.py
+31Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,37 @@ def test_loader(self):
280280
self.assertEqual(linecache.getlines(filename, module_globals),
281281
['source for x.y.z\n'])
282282

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

284315
class LineCacheInvalidationTests(unittest.TestCase):
285316
def setUp(self):
+2Lines 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)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.