From 4cfbb0a627dec9f752f7bc6f2fbfa9b5e6976ac6 Mon Sep 17 00:00:00 2001 From: VanshAgarwal24036 Date: Tue, 27 Jan 2026 23:36:44 +0530 Subject: [PATCH 1/4] fix: prevent memoryview slice assignment crash on shared memory --- Lib/test/_test_multiprocessing.py | 9 +++++++++ .../2026-01-27-23-35-19.gh-issue-144281.IiakEV.rst | 2 ++ Objects/memoryobject.c | 5 +++++ 3 files changed, 16 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-01-27-23-35-19.gh-issue-144281.IiakEV.rst diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index cc07062eee6f98..91c4cc75a50d30 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -4987,6 +4987,15 @@ def test_shared_memory_tracking(self): resource_tracker.unregister(mem._name, "shared_memory") mem.close() + def test_shared_memory_slice_assignment_no_crash(): + from multiprocessing import shared_memory + shm = shared_memory.SharedMemory(create=True, size=10) + try: + shm.buf[:5] = b'hello' + finally: + shm.close() + shm.unlink() + # # Test to verify that `Finalize` works. # diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-27-23-35-19.gh-issue-144281.IiakEV.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-27-23-35-19.gh-issue-144281.IiakEV.rst new file mode 100644 index 00000000000000..b9561e49509fb6 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-27-23-35-19.gh-issue-144281.IiakEV.rst @@ -0,0 +1,2 @@ +Fix a possible interpreter crash during memoryview slice assignment when the +underlying buffer is backed by shared memory. diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c index f3b7e4a396b4a1..27819292425916 100644 --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -2656,6 +2656,11 @@ memory_ass_sub(PyObject *_self, PyObject *key, PyObject *value) CHECK_RELEASED_INT(self); + if (view->buf == NULL) { + PyErr_SetString(PyExc_BufferError, "memoryview: underlying buffer is no longer valid"); + return -1; + } + fmt = adjust_fmt(view); if (fmt == NULL) return -1; From 6745906724612c220fa2288ed57577382420332c Mon Sep 17 00:00:00 2001 From: VanshAgarwal24036 Date: Wed, 28 Jan 2026 00:02:11 +0530 Subject: [PATCH 2/4] test: fix test method signature for shared_memory slice assignment --- Lib/test/_test_multiprocessing.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index 91c4cc75a50d30..2ed270a3be859c 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -4932,6 +4932,15 @@ def test_shared_memory_cleaned_after_process_termination(self): "resource_tracker: There appear to be 1 leaked " "shared_memory objects to clean up at shutdown", err) + def test_shared_memory_slice_assignment_no_crash(self): + from multiprocessing import shared_memory + shm = shared_memory.SharedMemory(create=True, size=10) + try: + shm.buf[:5] = b'hello' + finally: + shm.close() + shm.unlink() + @unittest.skipIf(os.name != "posix", "resource_tracker is posix only") @resource_tracker_format_subtests def test_shared_memory_untracking(self): @@ -4987,15 +4996,6 @@ def test_shared_memory_tracking(self): resource_tracker.unregister(mem._name, "shared_memory") mem.close() - def test_shared_memory_slice_assignment_no_crash(): - from multiprocessing import shared_memory - shm = shared_memory.SharedMemory(create=True, size=10) - try: - shm.buf[:5] = b'hello' - finally: - shm.close() - shm.unlink() - # # Test to verify that `Finalize` works. # From 96d7a428b7bdef1e10f6fc988c74997a1159a586 Mon Sep 17 00:00:00 2001 From: VanshAgarwal24036 Date: Wed, 28 Jan 2026 09:44:07 +0530 Subject: [PATCH 3/4] Update Test --- Lib/test/_test_multiprocessing.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index 2ed270a3be859c..5d53d316e09258 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -4935,11 +4935,11 @@ def test_shared_memory_cleaned_after_process_termination(self): def test_shared_memory_slice_assignment_no_crash(self): from multiprocessing import shared_memory shm = shared_memory.SharedMemory(create=True, size=10) - try: - shm.buf[:5] = b'hello' - finally: - shm.close() - shm.unlink() + mv = shm.buf + shm.close() + shm.unlink() + with self.assertRaises(BufferError): + mv[:5] = b'hello' @unittest.skipIf(os.name != "posix", "resource_tracker is posix only") @resource_tracker_format_subtests From ad0591c44aef1a4daba33e2839fc634a8d7ae641 Mon Sep 17 00:00:00 2001 From: VanshAgarwal24036 Date: Wed, 28 Jan 2026 10:00:15 +0530 Subject: [PATCH 4/4] Resolve Test Error --- Lib/test/_test_multiprocessing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index 5d53d316e09258..c903ee7a7f1cb5 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -4938,7 +4938,7 @@ def test_shared_memory_slice_assignment_no_crash(self): mv = shm.buf shm.close() shm.unlink() - with self.assertRaises(BufferError): + with self.assertRaises((BufferError, ValueError)): mv[:5] = b'hello' @unittest.skipIf(os.name != "posix", "resource_tracker is posix only")