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 e85e8de

Browse filesBrowse files
authored
gh-118209: Add Windows structured exception handling to mmap module (GH-118213)
1 parent 7e6fcab commit e85e8de
Copy full SHA for e85e8de

File tree

4 files changed

+410
-48
lines changed
Filter options

4 files changed

+410
-48
lines changed

‎Doc/whatsnew/3.13.rst

Copy file name to clipboardExpand all lines: Doc/whatsnew/3.13.rst
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,9 @@ mmap
796796
* :class:`mmap.mmap` now has a *trackfd* parameter on Unix; if it is ``False``,
797797
the file descriptor specified by *fileno* will not be duplicated.
798798
(Contributed by Zackery Spytz and Petr Viktorin in :gh:`78502`.)
799+
* :class:`mmap.mmap` is now protected from crashing on Windows when the mapped memory
800+
is inaccessible due to file system errors or access violations.
801+
(Contributed by Jannis Weigend in :gh:`118209`.)
799802

800803
opcode
801804
------

‎Lib/test/test_mmap.py

Copy file name to clipboardExpand all lines: Lib/test/test_mmap.py
+77Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
)
44
from test.support.import_helper import import_module
55
from test.support.os_helper import TESTFN, unlink
6+
from test.support.script_helper import assert_python_ok
67
import unittest
78
import errno
89
import os
@@ -12,6 +13,7 @@
1213
import socket
1314
import string
1415
import sys
16+
import textwrap
1517
import weakref
1618

1719
# Skip test if we can't import mmap.
@@ -1058,6 +1060,81 @@ def __exit__(self, exc_type, exc_value, traceback):
10581060
with self.assertRaisesRegex(ValueError, "mmap closed or invalid"):
10591061
m.write_byte(X())
10601062

1063+
@unittest.skipUnless(os.name == 'nt', 'requires Windows')
1064+
@unittest.skipUnless(hasattr(mmap.mmap, '_protect'), 'test needs debug build')
1065+
def test_access_violations(self):
1066+
from test.support.os_helper import TESTFN
1067+
1068+
code = textwrap.dedent("""
1069+
import faulthandler
1070+
import mmap
1071+
import os
1072+
import sys
1073+
from contextlib import suppress
1074+
1075+
# Prevent logging access violations to stderr.
1076+
faulthandler.disable()
1077+
1078+
PAGESIZE = mmap.PAGESIZE
1079+
PAGE_NOACCESS = 0x01
1080+
1081+
with open(sys.argv[1], 'bw+') as f:
1082+
f.write(b'A'* PAGESIZE)
1083+
f.flush()
1084+
1085+
m = mmap.mmap(f.fileno(), PAGESIZE)
1086+
m._protect(PAGE_NOACCESS, 0, PAGESIZE)
1087+
with suppress(OSError):
1088+
m.read(PAGESIZE)
1089+
assert False, 'mmap.read() did not raise'
1090+
with suppress(OSError):
1091+
m.read_byte()
1092+
assert False, 'mmap.read_byte() did not raise'
1093+
with suppress(OSError):
1094+
m.readline()
1095+
assert False, 'mmap.readline() did not raise'
1096+
with suppress(OSError):
1097+
m.write(b'A'* PAGESIZE)
1098+
assert False, 'mmap.write() did not raise'
1099+
with suppress(OSError):
1100+
m.write_byte(0)
1101+
assert False, 'mmap.write_byte() did not raise'
1102+
with suppress(OSError):
1103+
m[0] # test mmap_subscript
1104+
assert False, 'mmap.__getitem__() did not raise'
1105+
with suppress(OSError):
1106+
m[0:10] # test mmap_subscript
1107+
assert False, 'mmap.__getitem__() did not raise'
1108+
with suppress(OSError):
1109+
m[0:10:2] # test mmap_subscript
1110+
assert False, 'mmap.__getitem__() did not raise'
1111+
with suppress(OSError):
1112+
m[0] = 1
1113+
assert False, 'mmap.__setitem__() did not raise'
1114+
with suppress(OSError):
1115+
m[0:10] = b'A'* 10
1116+
assert False, 'mmap.__setitem__() did not raise'
1117+
with suppress(OSError):
1118+
m[0:10:2] = b'A'* 5
1119+
assert False, 'mmap.__setitem__() did not raise'
1120+
with suppress(OSError):
1121+
m.move(0, 10, 1)
1122+
assert False, 'mmap.move() did not raise'
1123+
with suppress(OSError):
1124+
list(m) # test mmap_item
1125+
assert False, 'mmap.__getitem__() did not raise'
1126+
with suppress(OSError):
1127+
m.find(b'A')
1128+
assert False, 'mmap.find() did not raise'
1129+
with suppress(OSError):
1130+
m.rfind(b'A')
1131+
assert False, 'mmap.rfind() did not raise'
1132+
""")
1133+
rt, stdout, stderr = assert_python_ok("-c", code, TESTFN)
1134+
self.assertEqual(stdout.strip(), b'')
1135+
self.assertEqual(stderr.strip(), b'')
1136+
1137+
10611138
class LargeMmapTests(unittest.TestCase):
10621139

10631140
def setUp(self):
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Avoid crashing in :mod:`mmap` on Windows when the mapped memory is inaccessible
2+
due to file system errors or access violations.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.