From 954d1ae435490bbc7f1e17f5d507e4b19d00c2bb Mon Sep 17 00:00:00 2001 From: Eric Soroos Date: Fri, 13 Dec 2013 15:13:19 -0800 Subject: [PATCH 1/5] int->Py_ssize_t, fixes #436 --- map.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/map.c b/map.c index 5d080117a..15aaed27a 100644 --- a/map.c +++ b/map.c @@ -323,7 +323,7 @@ mapping_destroy_buffer(Imaging im) PyObject* PyImaging_MapBuffer(PyObject* self, PyObject* args) { - int y, size; + Py_ssize_t y, size; Imaging im; PyObject* target; @@ -331,12 +331,12 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args) char* mode; char* codec; PyObject* bbox; - int offset; + Py_ssize_t offset; int xsize, ysize; int stride; int ystep; - if (!PyArg_ParseTuple(args, "O(ii)sOi(sii)", &target, &xsize, &ysize, + if (!PyArg_ParseTuple(args, "O(ii)sOn(sii)", &target, &xsize, &ysize, &codec, &bbox, &offset, &mode, &stride, &ystep)) return NULL; @@ -354,7 +354,7 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args) stride = xsize * 4; } - size = ysize * stride; + size = (Py_ssize_t) ysize * stride; /* check buffer size */ if (PyImaging_GetBuffer(target, &view) < 0) From 631612edc61d278a751e8ebbf2d21b6c79f40fea Mon Sep 17 00:00:00 2001 From: Eric Soroos Date: Fri, 13 Dec 2013 15:13:43 -0800 Subject: [PATCH 2/5] mixed 8ch tabs + spaces -> 4 space indent --- map.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/map.c b/map.c index 15aaed27a..95d5d1d35 100644 --- a/map.c +++ b/map.c @@ -66,7 +66,7 @@ PyImaging_MapperNew(const char* filename, int readonly) mapper = PyObject_New(ImagingMapperObject, &ImagingMapperType); if (mapper == NULL) - return NULL; + return NULL; mapper->base = NULL; mapper->size = mapper->offset = 0; @@ -94,7 +94,7 @@ PyImaging_MapperNew(const char* filename, int readonly) PAGE_READONLY, 0, 0, NULL); if (mapper->hMap == (HANDLE)-1) { - CloseHandle(mapper->hFile); + CloseHandle(mapper->hFile); PyErr_SetString(PyExc_IOError, "cannot map file"); PyObject_Del(mapper); return NULL; @@ -116,11 +116,11 @@ mapping_dealloc(ImagingMapperObject* mapper) { #ifdef WIN32 if (mapper->base != 0) - UnmapViewOfFile(mapper->base); + UnmapViewOfFile(mapper->base); if (mapper->hMap != (HANDLE)-1) - CloseHandle(mapper->hMap); + CloseHandle(mapper->hMap); if (mapper->hFile != (HANDLE)-1) - CloseHandle(mapper->hFile); + CloseHandle(mapper->hFile); mapper->base = 0; mapper->hMap = mapper->hFile = (HANDLE)-1; #endif @@ -137,7 +137,7 @@ mapping_read(ImagingMapperObject* mapper, PyObject* args) int size = -1; if (!PyArg_ParseTuple(args, "|i", &size)) - return NULL; + return NULL; /* check size */ if (size < 0 || mapper->offset + size > mapper->size) @@ -147,7 +147,7 @@ mapping_read(ImagingMapperObject* mapper, PyObject* args) buf = PyBytes_FromStringAndSize(NULL, size); if (!buf) - return NULL; + return NULL; if (size > 0) { memcpy(PyBytes_AsString(buf), mapper->base + mapper->offset, size); @@ -163,7 +163,7 @@ mapping_seek(ImagingMapperObject* mapper, PyObject* args) int offset; int whence = 0; if (!PyArg_ParseTuple(args, "i|i", &offset, &whence)) - return NULL; + return NULL; switch (whence) { case 0: /* SEEK_SET */ @@ -208,7 +208,7 @@ mapping_readimage(ImagingMapperObject* mapper, PyObject* args) int orientation; if (!PyArg_ParseTuple(args, "s(ii)ii", &mode, &xsize, &ysize, &stride, &orientation)) - return NULL; + return NULL; if (stride <= 0) { /* FIXME: maybe we should call ImagingNewPrologue instead */ @@ -259,13 +259,13 @@ static struct PyMethodDef methods[] = { }; static PyTypeObject ImagingMapperType = { - PyVarObject_HEAD_INIT(NULL, 0) - "ImagingMapper", /*tp_name*/ - sizeof(ImagingMapperObject), /*tp_size*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)mapping_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ + PyVarObject_HEAD_INIT(NULL, 0) + "ImagingMapper", /*tp_name*/ + sizeof(ImagingMapperObject), /*tp_size*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor)mapping_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ @@ -297,7 +297,7 @@ PyImaging_Mapper(PyObject* self, PyObject* args) { char* filename; if (!PyArg_ParseTuple(args, "s", &filename)) - return NULL; + return NULL; return (PyObject*) PyImaging_MapperNew(filename, 1); } @@ -338,7 +338,7 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args) if (!PyArg_ParseTuple(args, "O(ii)sOn(sii)", &target, &xsize, &ysize, &codec, &bbox, &offset, &mode, &stride, &ystep)) - return NULL; + return NULL; if (!PyImaging_CheckBuffer(target)) { PyErr_SetString(PyExc_TypeError, "expected string or buffer"); From 1060a59de99e8deb218c15ae75f1b86c0b5eef61 Mon Sep 17 00:00:00 2001 From: Eric Soroos Date: Fri, 13 Dec 2013 15:16:14 -0800 Subject: [PATCH 3/5] int->py_ssize_t for potentially large numbers --- libImaging/Storage.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libImaging/Storage.c b/libImaging/Storage.c index 314f462c8..ecedea45f 100644 --- a/libImaging/Storage.c +++ b/libImaging/Storage.c @@ -325,15 +325,15 @@ Imaging ImagingNewBlock(const char *mode, int xsize, int ysize) { Imaging im; - int y, i; - int bytes; + Py_ssize_t y, i; + Py_ssize_t bytes; im = ImagingNewPrologue(mode, xsize, ysize); if (!im) return NULL; /* Use a single block */ - bytes = im->ysize * im->linesize; + bytes = (Py_ssize_t) im->ysize * im->linesize; if (bytes <= 0) /* some platforms return NULL for malloc(0); this fix prevents MemoryError on zero-sized images on such From ec6fd4d6728c9791795b08ea86ea30dd795fe914 Mon Sep 17 00:00:00 2001 From: Eric Soroos Date: Fri, 13 Dec 2013 15:17:43 -0800 Subject: [PATCH 4/5] mixed 8ch tabs + spaces -> 4 space indent --- libImaging/Storage.c | 66 ++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/libImaging/Storage.c b/libImaging/Storage.c index ecedea45f..d31db5cb2 100644 --- a/libImaging/Storage.c +++ b/libImaging/Storage.c @@ -54,7 +54,7 @@ ImagingNewPrologueSubtype(const char *mode, unsigned xsize, unsigned ysize, im = (Imaging) calloc(1, size); if (!im) - return (Imaging) ImagingError_MemoryError(); + return (Imaging) ImagingError_MemoryError(); /* Setup image descriptor */ im->xsize = xsize; @@ -106,7 +106,7 @@ ImagingNewPrologueSubtype(const char *mode, unsigned xsize, unsigned ysize, im->type = IMAGING_TYPE_INT32; } else if (strcmp(mode, "I;16") == 0 || strcmp(mode, "I;16L") == 0 \ - || strcmp(mode, "I;16B") == 0 || strcmp(mode, "I;16N") == 0) { + || strcmp(mode, "I;16B") == 0 || strcmp(mode, "I;16N") == 0) { /* EXPERIMENTAL */ /* 16-bit raw integer images */ im->bands = 1; @@ -203,8 +203,8 @@ ImagingNewPrologueSubtype(const char *mode, unsigned xsize, unsigned ysize, ImagingSectionLeave(&cookie); if (!im->image) { - free(im); - return (Imaging) ImagingError_MemoryError(); + free(im); + return (Imaging) ImagingError_MemoryError(); } ImagingNewCount++; @@ -227,16 +227,16 @@ ImagingNewEpilogue(Imaging im) assume that it couldn't allocate the required amount of memory. */ if (!im->destroy) - return (Imaging) ImagingError_MemoryError(); + return (Imaging) ImagingError_MemoryError(); /* Initialize alias pointers to pixel data. */ switch (im->pixelsize) { case 1: case 2: case 3: - im->image8 = (UINT8 **) im->image; - break; + im->image8 = (UINT8 **) im->image; + break; case 4: - im->image32 = (INT32 **) im->image; - break; + im->image32 = (INT32 **) im->image; + break; } return im; @@ -246,16 +246,16 @@ void ImagingDelete(Imaging im) { if (!im) - return; + return; if (im->palette) - ImagingPaletteDelete(im->palette); + ImagingPaletteDelete(im->palette); if (im->destroy) - im->destroy(im); + im->destroy(im); if (im->image) - free(im->image); + free(im->image); free(im); } @@ -271,9 +271,9 @@ ImagingDestroyArray(Imaging im) int y; if (im->image) - for (y = 0; y < im->ysize; y++) - if (im->image[y]) - free(im->image[y]); + for (y = 0; y < im->ysize; y++) + if (im->image[y]) + free(im->image[y]); } Imaging @@ -287,24 +287,24 @@ ImagingNewArray(const char *mode, int xsize, int ysize) im = ImagingNewPrologue(mode, xsize, ysize); if (!im) - return NULL; + return NULL; ImagingSectionEnter(&cookie); /* Allocate image as an array of lines */ for (y = 0; y < im->ysize; y++) { - p = (char *) malloc(im->linesize); - if (!p) { - ImagingDestroyArray(im); - break; - } + p = (char *) malloc(im->linesize); + if (!p) { + ImagingDestroyArray(im); + break; + } im->image[y] = p; } ImagingSectionLeave(&cookie); if (y == im->ysize) - im->destroy = ImagingDestroyArray; + im->destroy = ImagingDestroyArray; return ImagingNewEpilogue(im); } @@ -318,7 +318,7 @@ static void ImagingDestroyBlock(Imaging im) { if (im->block) - free(im->block); + free(im->block); } Imaging @@ -330,7 +330,7 @@ ImagingNewBlock(const char *mode, int xsize, int ysize) im = ImagingNewPrologue(mode, xsize, ysize); if (!im) - return NULL; + return NULL; /* Use a single block */ bytes = (Py_ssize_t) im->ysize * im->linesize; @@ -344,12 +344,12 @@ ImagingNewBlock(const char *mode, int xsize, int ysize) if (im->block) { memset(im->block, 0, bytes); - for (y = i = 0; y < im->ysize; y++) { - im->image[y] = im->block + i; - i += im->linesize; - } + for (y = i = 0; y < im->ysize; y++) { + im->image[y] = im->block + i; + i += im->linesize; + } - im->destroy = ImagingDestroyBlock; + im->destroy = ImagingDestroyBlock; } @@ -360,9 +360,9 @@ ImagingNewBlock(const char *mode, int xsize, int ysize) * Create a new, internally allocated, image. */ #if defined(IMAGING_SMALL_MODEL) -#define THRESHOLD 16384L +#define THRESHOLD 16384L #else -#define THRESHOLD (2048*2048*4L) +#define THRESHOLD (2048*2048*4L) #endif Imaging @@ -418,6 +418,6 @@ ImagingCopyInfo(Imaging destination, Imaging source) if (source->palette) { if (destination->palette) ImagingPaletteDelete(destination->palette); - destination->palette = ImagingPaletteDuplicate(source->palette); + destination->palette = ImagingPaletteDuplicate(source->palette); } } From 77008c0b622bf021b45b929af3b7150cdc036f13 Mon Sep 17 00:00:00 2001 From: Eric Soroos Date: Fri, 13 Dec 2013 21:02:27 -0800 Subject: [PATCH 5/5] test for 2gb numpy image segfault --- Tests/large_memory_numpy_test.py | 37 ++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 Tests/large_memory_numpy_test.py diff --git a/Tests/large_memory_numpy_test.py b/Tests/large_memory_numpy_test.py new file mode 100644 index 000000000..eb9b8aa01 --- /dev/null +++ b/Tests/large_memory_numpy_test.py @@ -0,0 +1,37 @@ +from tester import * + +# This test is not run automatically. +# +# It requires > 2gb memory for the >2 gigapixel image generated in the +# second test. Running this automatically would amount to a denial of +# service on our testing infrastructure. I expect this test to fail +# on any 32 bit machine, as well as any smallish things (like +# raspberrypis). + +from PIL import Image +try: + import numpy as np +except: + skip() + +ydim = 32769 +xdim = 48000 +f = tempfile('temp.png') + +def _write_png(xdim,ydim): + dtype = np.uint8 + a = np.zeros((xdim, ydim), dtype=dtype) + im = Image.fromarray(a, 'L') + im.save(f) + success() + +def test_large(): + """ succeeded prepatch""" + _write_png(xdim,ydim) +def test_2gpx(): + """failed prepatch""" + _write_png(xdim,xdim) + + + +