Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
handle NUL bytes
  • Loading branch information
picnixz committed Jul 24, 2024
commit 0b57bb45372b7cf4a5fda3b989ea49f8f991d2e1
27 changes: 11 additions & 16 deletions Lib/linecache.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,13 @@ def checkcache(filename=None):
return
try:
stat = os.stat(fullname)
except OSError:
cache.pop(filename, None)
continue
except ValueError:
# ValueError may happen on Windows platforms for long paths.
# In this case, we assume that we could not just read the file.
except (OSError, ValueError):
# ValueError may happen on Windows platforms for long paths or
# on any platform when the filename has embedded null bytes.
#
# See: https://github.com/python/cpython/issues/122170.
if os.name == 'nt':
cache.pop(filename, None)
continue
raise # this should not happen on other platforms
cache.pop(filename, None)
continue
if size != stat.st_size or mtime != stat.st_mtime:
cache.pop(filename, None)

Expand Down Expand Up @@ -144,16 +139,16 @@ def updatecache(filename, module_globals=None):
try:
stat = os.stat(fullname)
break
except OSError:
except (OSError, ValueError):
pass
except ValueError:
if os.name != 'nt':
raise # this should not happen on other platforms
else:
return []
except ValueError:
if os.name != 'nt':
raise # this should not happen on other platforms
# ValueError may happen on Windows platforms for long paths or
Comment thread
picnixz marked this conversation as resolved.
Outdated
# on any platform when the filename has embedded null bytes.
#
# In this case, we will not even try to find the path using lazy
# loading or alternative techniques.
return []
try:
with tokenize.open(fullname) as fp:
Expand Down
23 changes: 23 additions & 0 deletions Lib/test/test_linecache.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,28 @@ def test_loader(self):
self.assertEqual(linecache.getlines(filename, module_globals),
['source for x.y.z\n'])

def test_embedded_null_bytes(self):
NUL = '\x00'
Comment thread
picnixz marked this conversation as resolved.
Outdated
linecache.clearcache()
lines = linecache.updatecache(NUL)
self.assertListEqual(lines, [])
self.assertNotIn(NUL, linecache.cache)

# hack into the cache (it shouldn't be allowed
# but we never know what people do...)
linecache.clearcache()
linecache.cache[NUL] = (0, 1234, [], 'FULLNAME')
linecache.checkcache(NUL)
self.assertNotIn(NUL, linecache.cache)

linecache.clearcache()
linecache.cache[NUL] = (0, 1234, [], NUL)
linecache.checkcache(NUL)
self.assertNotIn(NUL, linecache.cache)

# just to be sure that we did not mess with cache
linecache.clearcache()

def test_long_filename(self):
# For POSIX platforms, an OSError will be raised and will take
# the usual path handling. For Windows platforms, a ValueError
Expand All @@ -295,6 +317,7 @@ def test_long_filename(self):

# hack into the cache (it shouldn't be allowed
# but we never know what people do...)
linecache.clearcache()
linecache.cache['smallname'] = (0, 1234, [], 'a' * 9999)
linecache.checkcache('smallname')
self.assertNotIn('smallname', linecache.cache)
Expand Down