| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 2801b3f commit dbb011a
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -407,7 +407,6 @@ def test_move(self): | |||
| 407 | 407 | m.move(0, 0, 1) | |
| 408 | 408 | m.move(0, 0, 0) | |
| 409 | 409 | ||
| 410 | - | ||
| 411 | 410 | def test_anonymous(self): | |
| 412 | 411 | # anonymous mmap.mmap(-1, PAGE) | |
| 413 | 412 | m = mmap.mmap(-1, PAGESIZE) | |
@@ -887,6 +886,92 @@ def test_resize_succeeds_with_error_for_second_named_mapping(self): | |||
| 887 | 886 | self.assertEqual(m1[:data_length], data) | |
| 888 | 887 | self.assertEqual(m2[:data_length], data) | |
| 889 | 888 | ||
| 889 | + def test_mmap_closed_by_int_scenarios(self): | ||
| 890 | + """ | ||
| 891 | + gh-103987: Test that mmap objects raise ValueError | ||
| 892 | + for closed mmap files | ||
| 893 | + """ | ||
| 894 | + | ||
| 895 | + class MmapClosedByIntContext: | ||
| 896 | + def __init__(self, access) -> None: | ||
| 897 | + self.access = access | ||
| 898 | + | ||
| 899 | + def __enter__(self): | ||
| 900 | + self.f = open(TESTFN, "w+b") | ||
| 901 | + self.f.write(random.randbytes(100)) | ||
| 902 | + self.f.flush() | ||
| 903 | + | ||
| 904 | + m = mmap.mmap(self.f.fileno(), 100, access=self.access) | ||
| 905 | + | ||
| 906 | + class X: | ||
| 907 | + def __index__(self): | ||
| 908 | + m.close() | ||
| 909 | + return 10 | ||
| 910 | + | ||
| 911 | + return (m, X) | ||
| 912 | + | ||
| 913 | + def __exit__(self, exc_type, exc_value, traceback): | ||
| 914 | + self.f.close() | ||
| 915 | + | ||
| 916 | + read_access_modes = [ | ||
| 917 | + mmap.ACCESS_READ, | ||
| 918 | + mmap.ACCESS_WRITE, | ||
| 919 | + mmap.ACCESS_COPY, | ||
| 920 | + mmap.ACCESS_DEFAULT, | ||
| 921 | + ] | ||
| 922 | + | ||
| 923 | + write_access_modes = [ | ||
| 924 | + mmap.ACCESS_WRITE, | ||
| 925 | + mmap.ACCESS_COPY, | ||
| 926 | + mmap.ACCESS_DEFAULT, | ||
| 927 | + ] | ||
| 928 | + | ||
| 929 | + for access in read_access_modes: | ||
| 930 | + with MmapClosedByIntContext(access) as (m, X): | ||
| 931 | + with self.assertRaisesRegex(ValueError, "mmap closed or invalid"): | ||
| 932 | + m[X()] | ||
| 933 | + | ||
| 934 | + with MmapClosedByIntContext(access) as (m, X): | ||
| 935 | + with self.assertRaisesRegex(ValueError, "mmap closed or invalid"): | ||
| 936 | + m[X() : 20] | ||
| 937 | + | ||
| 938 | + with MmapClosedByIntContext(access) as (m, X): | ||
| 939 | + with self.assertRaisesRegex(ValueError, "mmap closed or invalid"): | ||
| 940 | + m[X() : 20 : 2] | ||
| 941 | + | ||
| 942 | + with MmapClosedByIntContext(access) as (m, X): | ||
| 943 | + with self.assertRaisesRegex(ValueError, "mmap closed or invalid"): | ||
| 944 | + m[20 : X() : -2] | ||
| 945 | + | ||
| 946 | + with MmapClosedByIntContext(access) as (m, X): | ||
| 947 | + with self.assertRaisesRegex(ValueError, "mmap closed or invalid"): | ||
| 948 | + m.read(X()) | ||
| 949 | + | ||
| 950 | + with MmapClosedByIntContext(access) as (m, X): | ||
| 951 | + with self.assertRaisesRegex(ValueError, "mmap closed or invalid"): | ||
| 952 | + m.find(b"1", 1, X()) | ||
| 953 | + | ||
| 954 | + for access in write_access_modes: | ||
| 955 | + with MmapClosedByIntContext(access) as (m, X): | ||
| 956 | + with self.assertRaisesRegex(ValueError, "mmap closed or invalid"): | ||
| 957 | + m[X() : 20] = b"1" * 10 | ||
| 958 | + | ||
| 959 | + with MmapClosedByIntContext(access) as (m, X): | ||
| 960 | + with self.assertRaisesRegex(ValueError, "mmap closed or invalid"): | ||
| 961 | + m[X() : 20 : 2] = b"1" * 5 | ||
| 962 | + | ||
| 963 | + with MmapClosedByIntContext(access) as (m, X): | ||
| 964 | + with self.assertRaisesRegex(ValueError, "mmap closed or invalid"): | ||
| 965 | + m[20 : X() : -2] = b"1" * 5 | ||
| 966 | + | ||
| 967 | + with MmapClosedByIntContext(access) as (m, X): | ||
| 968 | + with self.assertRaisesRegex(ValueError, "mmap closed or invalid"): | ||
| 969 | + m.move(1, 2, X()) | ||
| 970 | + | ||
| 971 | + with MmapClosedByIntContext(access) as (m, X): | ||
| 972 | + with self.assertRaisesRegex(ValueError, "mmap closed or invalid"): | ||
| 973 | + m.write_byte(X()) | ||
| 974 | + | ||
| 890 | 975 | class LargeMmapTests(unittest.TestCase): | |
| 891 | 976 | ||
| 892 | 977 | def setUp(self): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,2 @@ | |||
| 1 | + In :mod:`mmap`, fix several bugs that could lead to access to memory-mapped files after | ||
| 2 | + they have been invalidated. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -292,7 +292,8 @@ mmap_read_method(mmap_object *self, | |||
| 292 | 292 | ||
| 293 | 293 | CHECK_VALID(NULL); | |
| 294 | 294 | if (!PyArg_ParseTuple(args, "|O&:read", _Py_convert_optional_to_ssize_t, &num_bytes)) | |
| 295 | - return(NULL); | ||
| 295 | + return NULL; | ||
| 296 | + CHECK_VALID(NULL); | ||
| 296 | 297 | ||
| 297 | 298 | /* silently 'adjust' out-of-range requests */ | |
| 298 | 299 | remaining = (self->pos < self->size) ? self->size - self->pos : 0; | |
@@ -333,6 +334,7 @@ mmap_gfind(mmap_object *self, | |||
| 333 | 334 | end = self->size; | |
| 334 | 335 | ||
| 335 | 336 | Py_ssize_t res; | |
| 337 | + CHECK_VALID(NULL); | ||
| 336 | 338 | if (reverse) { | |
| 337 | 339 | res = _PyBytes_ReverseFind( | |
| 338 | 340 | self->data + start, end - start, | |
@@ -396,7 +398,7 @@ mmap_write_method(mmap_object *self, | |||
| 396 | 398 | ||
| 397 | 399 | CHECK_VALID(NULL); | |
| 398 | 400 | if (!PyArg_ParseTuple(args, "y*:write", &data)) | |
| 399 | - return(NULL); | ||
| 401 | + return NULL; | ||
| 400 | 402 | ||
| 401 | 403 | if (!is_writable(self)) { | |
| 402 | 404 | PyBuffer_Release(&data); | |
@@ -409,6 +411,7 @@ mmap_write_method(mmap_object *self, | |||
| 409 | 411 | return NULL; | |
| 410 | 412 | } | |
| 411 | 413 | ||
| 414 | + CHECK_VALID(NULL); | ||
| 412 | 415 | memcpy(&self->data[self->pos], data.buf, data.len); | |
| 413 | 416 | self->pos += data.len; | |
| 414 | 417 | PyBuffer_Release(&data); | |
@@ -428,6 +431,7 @@ mmap_write_byte_method(mmap_object *self, | |||
| 428 | 431 | if (!is_writable(self)) | |
| 429 | 432 | return NULL; | |
| 430 | 433 | ||
| 434 | + CHECK_VALID(NULL); | ||
| 431 | 435 | if (self->pos < self->size) { | |
| 432 | 436 | self->data[self->pos++] = value; | |
| 433 | 437 | Py_RETURN_NONE; | |
@@ -732,6 +736,7 @@ mmap_move_method(mmap_object *self, PyObject *args) | |||
| 732 | 736 | if (self->size - dest < cnt || self->size - src < cnt) | |
| 733 | 737 | goto bounds; | |
| 734 | 738 | ||
| 739 | + CHECK_VALID(NULL); | ||
| 735 | 740 | memmove(&self->data[dest], &self->data[src], cnt); | |
| 736 | 741 | ||
| 737 | 742 | Py_RETURN_NONE; | |
@@ -857,6 +862,7 @@ mmap_madvise_method(mmap_object *self, PyObject *args) | |||
| 857 | 862 | length = self->size - start; | |
| 858 | 863 | } | |
| 859 | 864 | ||
| 865 | + CHECK_VALID(NULL); | ||
| 860 | 866 | if (madvise(self->data + start, length, option) != 0) { | |
| 861 | 867 | PyErr_SetFromErrno(PyExc_OSError); | |
| 862 | 868 | return NULL; | |
@@ -955,6 +961,7 @@ mmap_subscript(mmap_object *self, PyObject *item) | |||
| 955 | 961 | "mmap index out of range"); | |
| 956 | 962 | return NULL; | |
| 957 | 963 | } | |
| 964 | + CHECK_VALID(NULL); | ||
| 958 | 965 | return PyLong_FromLong(Py_CHARMASK(self->data[i])); | |
| 959 | 966 | } | |
| 960 | 967 | else if (PySlice_Check(item)) { | |
@@ -965,6 +972,7 @@ mmap_subscript(mmap_object *self, PyObject *item) | |||
| 965 | 972 | } | |
| 966 | 973 | slicelen = PySlice_AdjustIndices(self->size, &start, &stop, step); | |
| 967 | 974 | ||
| 975 | + CHECK_VALID(NULL); | ||
| 968 | 976 | if (slicelen <= 0) | |
| 969 | 977 | return PyBytes_FromStringAndSize("", 0); | |
| 970 | 978 | else if (step == 1) | |
@@ -978,6 +986,7 @@ mmap_subscript(mmap_object *self, PyObject *item) | |||
| 978 | 986 | ||
| 979 | 987 | if (result_buf == NULL) | |
| 980 | 988 | return PyErr_NoMemory(); | |
| 989 | + | ||
| 981 | 990 | for (cur = start, i = 0; i < slicelen; | |
| 982 | 991 | cur += step, i++) { | |
| 983 | 992 | result_buf[i] = self->data[cur]; | |
@@ -1062,6 +1071,7 @@ mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value) | |||
| 1062 | 1071 | "in range(0, 256)"); | |
| 1063 | 1072 | return -1; | |
| 1064 | 1073 | } | |
| 1074 | + CHECK_VALID(-1); | ||
| 1065 | 1075 | self->data[i] = (char) v; | |
| 1066 | 1076 | return 0; | |
| 1067 | 1077 | } | |
@@ -1087,6 +1097,7 @@ mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value) | |||
| 1087 | 1097 | return -1; | |
| 1088 | 1098 | } | |
| 1089 | 1099 | ||
| 1100 | + CHECK_VALID(-1); | ||
| 1090 | 1101 | if (slicelen == 0) { | |
| 1091 | 1102 | } | |
| 1092 | 1103 | else if (step == 1) { | |
| Back | FazBrowse Home | New Git URL |
0 commit comments