Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 2 additions & 2 deletions Doc/library/mmap.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ To map anonymous memory, -1 should be passed as the fileno along with the length
the same file. If you specify the name of an existing tag, that tag is
opened, otherwise a new tag of this name is created. If this parameter is
omitted or ``None``, the mapping is created without a name. Avoiding the
use of the tag parameter will assist in keeping your code portable between
Unix and Windows.
use of the *tagname* parameter will assist in keeping your code portable
between Unix and Windows.

*offset* may be specified as a non-negative integer offset. mmap references
will be relative to the offset from the beginning of the file. *offset*
Expand Down
6 changes: 4 additions & 2 deletions Lib/test/test_mmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -671,14 +671,16 @@ def test_tagname(self):
m2.close()
m1.close()

with self.assertRaisesRegex(TypeError, 'tagname'):
mmap.mmap(-1, 8, tagname=1)

@cpython_only
@unittest.skipUnless(os.name == 'nt', 'requires Windows')
def test_sizeof(self):
m1 = mmap.mmap(-1, 100)
tagname = random_tagname()
m2 = mmap.mmap(-1, 100, tagname=tagname)
self.assertEqual(sys.getsizeof(m2),
sys.getsizeof(m1) + len(tagname) + 1)
self.assertGreater(sys.getsizeof(m2), sys.getsizeof(m1))

@unittest.skipUnless(os.name == 'nt', 'requires Windows')
def test_crasher_on_windows(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix mojibake in :class:`mmap.mmap` when using a non-ASCII *tagname* argument
on Windows.
47 changes: 24 additions & 23 deletions Modules/mmapmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ typedef struct {
#ifdef MS_WINDOWS
HANDLE map_handle;
HANDLE file_handle;
char * tagname;
wchar_t * tagname;
#endif

#ifdef UNIX
Expand Down Expand Up @@ -539,7 +539,7 @@ mmap_resize_method(mmap_object *self,
CloseHandle(self->map_handle);
/* if the file mapping still exists, it cannot be resized. */
if (self->tagname) {
self->map_handle = OpenFileMapping(FILE_MAP_WRITE, FALSE,
self->map_handle = OpenFileMappingW(FILE_MAP_WRITE, FALSE,
self->tagname);
if (self->map_handle) {
PyErr_SetFromWindowsErr(ERROR_USER_MAPPED_FILE);
Expand Down Expand Up @@ -568,7 +568,7 @@ mmap_resize_method(mmap_object *self,

/* create a new file mapping and map a new view */
/* FIXME: call CreateFileMappingW with wchar_t tagname */
self->map_handle = CreateFileMapping(
self->map_handle = CreateFileMappingW(
self->file_handle,
NULL,
PAGE_READWRITE,
Expand Down Expand Up @@ -843,12 +843,11 @@ mmap__repr__method(PyObject *self)
static PyObject *
mmap__sizeof__method(mmap_object *self, void *unused)
{
Py_ssize_t res;

res = _PyObject_SIZE(Py_TYPE(self));
if (self->tagname)
res += strlen(self->tagname) + 1;
return PyLong_FromSsize_t(res);
size_t res = _PyObject_SIZE(Py_TYPE(self));
if (self->tagname) {
res += (wcslen(self->tagname) + 1) * sizeof(self->tagname[0]);
}
return PyLong_FromSize_t(res);
}
#endif

Expand Down Expand Up @@ -1400,7 +1399,7 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
DWORD off_lo; /* lower 32 bits of offset */
DWORD size_hi; /* upper 32 bits of size */
DWORD size_lo; /* lower 32 bits of size */
const char *tagname = "";
PyObject *tagname = Py_None;
DWORD dwErr = 0;
int fileno;
HANDLE fh = 0;
Expand All @@ -1410,7 +1409,7 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
"tagname",
"access", "offset", NULL };

if (!PyArg_ParseTupleAndKeywords(args, kwdict, "in|ziL", keywords,
if (!PyArg_ParseTupleAndKeywords(args, kwdict, "in|OiL", keywords,
&fileno, &map_size,
&tagname, &access, &offset)) {
return NULL;
Expand Down Expand Up @@ -1543,17 +1542,19 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
m_obj->weakreflist = NULL;
m_obj->exports = 0;
/* set the tag name */
if (tagname != NULL && *tagname != '\0') {
m_obj->tagname = PyMem_Malloc(strlen(tagname)+1);
if (!Py_IsNone(tagname)) {
if (!PyUnicode_Check(tagname)) {
Py_DECREF(m_obj);
return PyErr_Format(PyExc_TypeError, "expected str or None for "
"'tagname', not %.200s",
Py_TYPE(tagname)->tp_name);
}
m_obj->tagname = PyUnicode_AsWideCharString(tagname, NULL);
if (m_obj->tagname == NULL) {
PyErr_NoMemory();
Py_DECREF(m_obj);
return NULL;
}
strcpy(m_obj->tagname, tagname);
}
else
m_obj->tagname = NULL;

m_obj->access = (access_mode)access;
size_hi = (DWORD)(size >> 32);
Expand All @@ -1562,12 +1563,12 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
off_lo = (DWORD)(offset & 0xFFFFFFFF);
/* For files, it would be sufficient to pass 0 as size.
For anonymous maps, we have to pass the size explicitly. */
m_obj->map_handle = CreateFileMapping(m_obj->file_handle,
NULL,
flProtect,
size_hi,
size_lo,
m_obj->tagname);
m_obj->map_handle = CreateFileMappingW(m_obj->file_handle,
NULL,
flProtect,
size_hi,
size_lo,
m_obj->tagname);
if (m_obj->map_handle != NULL) {
m_obj->data = (char *) MapViewOfFile(m_obj->map_handle,
dwDesiredAccess,
Expand Down