Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-118209: Add structured exception handling to mmap module #118213

Merged
merged 35 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
4013627
add structured exception handling to mmap_read_method
Dobatymo Apr 24, 2024
6484134
📜🤖 Added by blurb_it.
blurb-it[bot] Apr 24, 2024
71218d2
adjust indentation
Dobatymo Apr 24, 2024
cd4b1fc
restructure to use safe_memcpy to avoid memory leak
Dobatymo Apr 25, 2024
cb1ef19
Apply suggestions from code review
Dobatymo Apr 25, 2024
448fa90
fix passing dest as pointer in mmap_read_byte_method
Dobatymo Apr 26, 2024
ba96163
use PyBytes_AS_STRING instead of raw access
Dobatymo Apr 26, 2024
f97d213
handle mmap_write_method
Dobatymo Apr 26, 2024
7983869
handle mmap_write_byte_method
Dobatymo Apr 26, 2024
c0bd57b
add safe_byte_copy, safe_memmove, safe_memchr, safe_copy_from_slice a…
Dobatymo Apr 30, 2024
92f4bf0
improve macro
Dobatymo May 1, 2024
364d846
Update Modules/mmapmodule.c
Dobatymo May 1, 2024
04dc2d9
handle EXCEPTION_ACCESS_VIOLATION
Dobatymo May 2, 2024
0654f9b
fix formatting
Dobatymo May 2, 2024
d3661ff
use PyBytes_FromStringAndSize instead of extracting the optization
Dobatymo May 2, 2024
30aa64b
update news entry
Dobatymo May 3, 2024
b809ce9
Update Misc/NEWS.d/next/Windows/2024-04-24-05-16-32.gh-issue-118209.R…
Dobatymo May 6, 2024
e907e6d
updated whatsnew entry
Dobatymo May 6, 2024
d1ad0ab
fix typo
Dobatymo May 6, 2024
2ca440d
fix handling some cases in mmap_subscript
Dobatymo May 6, 2024
f7c356c
add test using private function
Dobatymo May 6, 2024
0d70108
Update Lib/test/test_mmap.py
Dobatymo May 6, 2024
6f1f726
run test in subprocess
Dobatymo May 6, 2024
05e8ca0
add expected failure for find method
Dobatymo May 6, 2024
29b12bf
disable faulthandler
Dobatymo May 6, 2024
59e8c4e
typo
Dobatymo May 6, 2024
4f610a5
trailing blanks
Dobatymo May 6, 2024
aa2b41d
Update Lib/test/test_mmap.py
Dobatymo May 6, 2024
11fa04a
add asserts to tests
Dobatymo May 6, 2024
f02c83a
Update Lib/test/test_mmap.py
Dobatymo May 7, 2024
8533af5
support mmap_gfind
Dobatymo May 7, 2024
6aeaa32
aesthetics
Dobatymo May 7, 2024
9737f22
Apply suggestions from code review
Dobatymo May 7, 2024
12fb561
remove restrict for compliance with the python C dialect
Dobatymo May 8, 2024
880a9c0
Update Modules/mmapmodule.c
Dobatymo May 8, 2024
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
3 changes: 3 additions & 0 deletions Doc/whatsnew/3.13.rst
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,9 @@ mmap
* :class:`mmap.mmap` now has a *trackfd* parameter on Unix; if it is ``False``,
the file descriptor specified by *fileno* will not be duplicated.
(Contributed by Zackery Spytz and Petr Viktorin in :gh:`78502`.)
* :class:`mmap.mmap` is now protected from crashing on Windows when the mapped memory
is inaccessible due to file system errors or access violations.
(Contributed by Jannis Weigend in :gh:`118209`.)

opcode
------
Expand Down
77 changes: 77 additions & 0 deletions Lib/test/test_mmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
)
from test.support.import_helper import import_module
from test.support.os_helper import TESTFN, unlink
from test.support.script_helper import assert_python_ok
import unittest
import errno
import os
Expand All @@ -12,6 +13,7 @@
import socket
import string
import sys
import textwrap
import weakref

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

@unittest.skipUnless(os.name == 'nt', 'requires Windows')
Dobatymo marked this conversation as resolved.
Show resolved Hide resolved
@unittest.skipUnless(hasattr(mmap.mmap, '_protect'), 'test needs debug build')
def test_access_violations(self):
from test.support.os_helper import TESTFN

code = textwrap.dedent("""
import faulthandler
import mmap
import os
import sys
from contextlib import suppress

# Prevent logging access violations to stderr.
faulthandler.disable()
Dobatymo marked this conversation as resolved.
Show resolved Hide resolved

PAGESIZE = mmap.PAGESIZE
PAGE_NOACCESS = 0x01

with open(sys.argv[1], 'bw+') as f:
f.write(b'A'* PAGESIZE)
f.flush()

m = mmap.mmap(f.fileno(), PAGESIZE)
m._protect(PAGE_NOACCESS, 0, PAGESIZE)
with suppress(OSError):
zooba marked this conversation as resolved.
Show resolved Hide resolved
m.read(PAGESIZE)
assert False, 'mmap.read() did not raise'
with suppress(OSError):
m.read_byte()
assert False, 'mmap.read_byte() did not raise'
with suppress(OSError):
m.readline()
assert False, 'mmap.readline() did not raise'
with suppress(OSError):
m.write(b'A'* PAGESIZE)
assert False, 'mmap.write() did not raise'
with suppress(OSError):
m.write_byte(0)
assert False, 'mmap.write_byte() did not raise'
with suppress(OSError):
m[0] # test mmap_subscript
assert False, 'mmap.__getitem__() did not raise'
with suppress(OSError):
m[0:10] # test mmap_subscript
assert False, 'mmap.__getitem__() did not raise'
with suppress(OSError):
m[0:10:2] # test mmap_subscript
assert False, 'mmap.__getitem__() did not raise'
with suppress(OSError):
m[0] = 1
assert False, 'mmap.__setitem__() did not raise'
with suppress(OSError):
m[0:10] = b'A'* 10
assert False, 'mmap.__setitem__() did not raise'
with suppress(OSError):
m[0:10:2] = b'A'* 5
assert False, 'mmap.__setitem__() did not raise'
with suppress(OSError):
m.move(0, 10, 1)
assert False, 'mmap.move() did not raise'
with suppress(OSError):
list(m) # test mmap_item
assert False, 'mmap.__getitem__() did not raise'
with suppress(OSError):
m.find(b'A')
assert False, 'mmap.find() did not raise'
with suppress(OSError):
m.rfind(b'A')
assert False, 'mmap.rfind() did not raise'
""")
rt, stdout, stderr = assert_python_ok("-c", code, TESTFN)
self.assertEqual(stdout.strip(), b'')
self.assertEqual(stderr.strip(), b'')


class LargeMmapTests(unittest.TestCase):

def setUp(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Avoid crashing in :mod:`mmap` on Windows when the mapped memory is inaccessible
due to file system errors or access violations.
Loading
Loading