diff -r d35dbf596638 -r a8aa2edb7e67 Lib/test/test_mmap.py --- a/Lib/test/test_mmap.py Tue Feb 08 00:10:33 2011 +0100 +++ b/Lib/test/test_mmap.py Wed Feb 09 16:36:59 2011 +0200 @@ -1,4 +1,4 @@ -from test.support import TESTFN, run_unittest, import_module +from test.support import TESTFN, run_unittest, import_module, unlink import unittest import os import re @@ -646,9 +646,57 @@ "wrong exception raised in context manager") self.assertTrue(m.closed, "context manager failed") +class LargeMmapTests(unittest.TestCase): + + def setUp(self): + unlink(TESTFN) + + def tearDown(self): + unlink(TESTFN) + + def _working_largefile(self): + # Only run if the current filesystem supports large files. + f = open(TESTFN, 'wb', buffering=0) + try: + f.seek(0x80000001) + f.write(b'x') + f.flush() + except (IOError, OverflowError): + raise unittest.SkipTest("filesystem does not have largefile support") + finally: + os.unlink(TESTFN) + f.close() + + def test_large_offset(self): + if sys.platform[:3] == 'win' or sys.platform == 'darwin': + requires('largefile', + 'test requires %s bytes and a long time to run' % str(0x180000000)) + self._working_largefile() + with open (TESTFN, 'wb') as f: + f.seek(0x17FFFFFFF) + f.write(b" ") + + with open (TESTFN, 'rb') as f: + with mmap.mmap(f.fileno(), 0, offset=0x140000000, access=mmap.ACCESS_READ) as m: + self.assertEqual(m[0x3FFFFFFF], 32) + + def test_large_filesize(self): + if sys.platform[:3] == 'win' or sys.platform == 'darwin': + requires('largefile', + 'test requires %s bytes and a long time to run' % str(0x180000000)) + self._working_largefile() + with open (TESTFN, 'wb') as f: + f.seek(0x17FFFFFFF) + f.write(b" ") + + with open (TESTFN, 'rb') as f: + with mmap.mmap(f.fileno(), 0x10000, access=mmap.ACCESS_READ) as m: + self.assertEqual(m.size(), 0x180000000) + def test_main(): run_unittest(MmapTests) + run_unittest(LargeMmapTests) if __name__ == '__main__': test_main() diff -r d35dbf596638 -r a8aa2edb7e67 Modules/mmapmodule.c --- a/Modules/mmapmodule.c Tue Feb 08 00:10:33 2011 +0100 +++ b/Modules/mmapmodule.c Wed Feb 09 16:36:59 2011 +0200 @@ -90,7 +90,7 @@ char * data; size_t size; size_t pos; /* relative to offset */ - size_t offset; + off_t offset; int exports; #ifdef MS_WINDOWS @@ -433,7 +433,11 @@ PyErr_SetFromErrno(mmap_module_error); return NULL; } - return PyLong_FromSsize_t(buf.st_size); +#ifdef HAVE_LARGEFILE_SUPPORT + return PyLong_FromLongLong(buf.st_size); +#else + return PyLong_FromLong(buf.st_size); +#endif } #endif /* UNIX */ } @@ -1051,6 +1055,12 @@ } #ifdef UNIX +#ifdef HAVE_LARGEFILE_SUPPORT +#define _Py_PARSE_OFF_T "L" +#else +#define _Py_PARSE_OFF_T "l" +#endif + static PyObject * new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict) { @@ -1058,8 +1068,9 @@ struct stat st; #endif mmap_object *m_obj; - PyObject *map_size_obj = NULL, *offset_obj = NULL; - Py_ssize_t map_size, offset; + PyObject *map_size_obj = NULL; + Py_ssize_t map_size; + off_t offset = 0; int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ; int devzero = -1; int access = (int)ACCESS_DEFAULT; @@ -1067,16 +1078,18 @@ "flags", "prot", "access", "offset", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|iiiO", keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|iii" _Py_PARSE_OFF_T, keywords, &fd, &map_size_obj, &flags, &prot, - &access, &offset_obj)) + &access, &offset)) return NULL; map_size = _GetMapSize(map_size_obj, "size"); if (map_size < 0) return NULL; - offset = _GetMapSize(offset_obj, "offset"); - if (offset < 0) + if (offset < 0) { + PyErr_SetString(PyExc_OverflowError, + "memory mapped offset must be positive"); return NULL; + } if ((access != (int)ACCESS_DEFAULT) && ((flags != MAP_SHARED) || (prot != (PROT_WRITE | PROT_READ)))) @@ -1121,8 +1134,14 @@ "mmap offset is greater than file size"); return NULL; } - map_size = st.st_size - offset; - } else if ((size_t)offset + (size_t)map_size > st.st_size) { + off_t calc_size = st.st_size - offset; + map_size = calc_size; + if (map_size != calc_size) { + PyErr_SetString(PyExc_ValueError, + "mmap length is too large"); + return NULL; + } + } else if (offset + (size_t)map_size > st.st_size) { PyErr_SetString(PyExc_ValueError, "mmap length is greater than file size"); return NULL;