diff --git a/_imaging.c b/_imaging.c index a282bb36a..0acd92b86 100644 --- a/_imaging.c +++ b/_imaging.c @@ -362,9 +362,20 @@ getbands(const char* mode) #define TYPE_DOUBLE (0x400|sizeof(double)) static void* -getlist(PyObject* arg, int* length, const char* wrong_length, int type) +getlist(PyObject* arg, Py_ssize_t* length, const char* wrong_length, int type) { - int i, n, itemp; + /* - allocates and returns a c array of the items in the + python sequence arg. + - the size of the returned array is in length + - all of the arg items must be numeric items of the type + specified in type + - sequence length is checked against the length parameter IF + an error parameter is passed in wrong_length + - caller is responsible for freeing the memory + */ + + Py_ssize_t i, n; + int itemp; double dtemp; void* list; PyObject* seq; @@ -381,7 +392,9 @@ getlist(PyObject* arg, int* length, const char* wrong_length, int type) return NULL; } - list = malloc(n * (type & 0xff)); + /* malloc check ok, type & ff is just a sizeof(something) + calloc checks for overflow */ + list = calloc(n, type & 0xff); if (!list) return PyErr_NoMemory(); @@ -845,7 +858,7 @@ static PyObject* _filter(ImagingObject* self, PyObject* args) { PyObject* imOut; - int kernelsize; + Py_ssize_t kernelsize; FLOAT32* kerneldata; int xsize, ysize; @@ -859,7 +872,7 @@ _filter(ImagingObject* self, PyObject* args) kerneldata = getlist(kernel, &kernelsize, NULL, TYPE_FLOAT32); if (!kerneldata) return NULL; - if (kernelsize != xsize * ysize) { + if (kernelsize != (Py_ssize_t) xsize * (Py_ssize_t) ysize) { free(kerneldata); return ImagingError_ValueError("bad kernel size"); } @@ -1148,8 +1161,8 @@ _point(ImagingObject* self, PyObject* args) { static const char* wrong_number = "wrong number of lut entries"; - int n, i; - int bands; + Py_ssize_t n; + int i, bands; Imaging im; PyObject* list; @@ -1614,7 +1627,7 @@ _transform2(ImagingObject* self, PyObject* args) static const char* wrong_number = "wrong number of matrix entries"; Imaging imOut; - int n; + Py_ssize_t n; double *a; ImagingObject* imagep; @@ -1849,6 +1862,7 @@ _getprojection(ImagingObject* self, PyObject* args) unsigned char* yprofile; PyObject* result; + /* malloc check ok */ xprofile = malloc(self->image->xsize); yprofile = malloc(self->image->ysize); @@ -2295,7 +2309,7 @@ _draw_dealloc(ImagingDrawObject* self) PyObject_Del(self); } -extern int PyPath_Flatten(PyObject* data, double **xy); +extern Py_ssize_t PyPath_Flatten(PyObject* data, double **xy); static PyObject* _draw_ink(ImagingDrawObject* self, PyObject* args) @@ -2316,7 +2330,7 @@ static PyObject* _draw_arc(ImagingDrawObject* self, PyObject* args) { double* xy; - int n; + Py_ssize_t n; PyObject* data; int ink; @@ -2352,7 +2366,7 @@ static PyObject* _draw_bitmap(ImagingDrawObject* self, PyObject* args) { double *xy; - int n; + Py_ssize_t n; PyObject *data; ImagingObject* bitmap; @@ -2388,7 +2402,7 @@ static PyObject* _draw_chord(ImagingDrawObject* self, PyObject* args) { double* xy; - int n; + Py_ssize_t n; PyObject* data; int ink, fill; @@ -2424,7 +2438,7 @@ static PyObject* _draw_ellipse(ImagingDrawObject* self, PyObject* args) { double* xy; - int n; + Py_ssize_t n; PyObject* data; int ink; @@ -2475,7 +2489,7 @@ static PyObject* _draw_lines(ImagingDrawObject* self, PyObject* args) { double *xy; - int i, n; + Py_ssize_t i, n; PyObject *data; int ink; @@ -2543,7 +2557,7 @@ static PyObject* _draw_points(ImagingDrawObject* self, PyObject* args) { double *xy; - int i, n; + Py_ssize_t i, n; PyObject *data; int ink; @@ -2605,7 +2619,7 @@ static PyObject* _draw_pieslice(ImagingDrawObject* self, PyObject* args) { double* xy; - int n; + Py_ssize_t n; PyObject* data; int ink, fill; @@ -2641,7 +2655,7 @@ _draw_polygon(ImagingDrawObject* self, PyObject* args) { double *xy; int *ixy; - int n, i; + Py_ssize_t n, i; PyObject* data; int ink; @@ -2660,7 +2674,7 @@ _draw_polygon(ImagingDrawObject* self, PyObject* args) } /* Copy list of vertices to array */ - ixy = (int*) malloc(n * 2 * sizeof(int)); + ixy = (int*) calloc(n, 2 * sizeof(int)); for (i = 0; i < n; i++) { ixy[i+i] = (int) xy[i+i]; @@ -2685,7 +2699,7 @@ static PyObject* _draw_rectangle(ImagingDrawObject* self, PyObject* args) { double* xy; - int n; + Py_ssize_t n; PyObject* data; int ink; diff --git a/decode.c b/decode.c index 29c0f9a1b..8313c25ad 100644 --- a/decode.c +++ b/decode.c @@ -188,8 +188,13 @@ _setimage(ImagingDecoderObject* decoder, PyObject* args) /* Allocate memory buffer (if bits field is set) */ if (state->bits > 0) { - if (!state->bytes) + if (!state->bytes) { + if (state->xsize > ((INT_MAX / state->bits)-7)){ + return PyErr_NoMemory(); + } state->bytes = (state->bits * state->xsize+7)/8; + } + /* malloc check ok, oveflow checked above */ state->buffer = (UINT8*) malloc(state->bytes); if (!state->buffer) return PyErr_NoMemory(); diff --git a/encode.c b/encode.c index 84e5b96b1..b9f553061 100644 --- a/encode.c +++ b/encode.c @@ -159,6 +159,7 @@ _encode_to_file(ImagingEncoderObject* encoder, PyObject* args) return NULL; /* Allocate an encoder buffer */ + /* malloc check ok, either constant int, or checked by PyArg_ParseTuple */ buf = (UINT8*) malloc(bufsize); if (!buf) return PyErr_NoMemory(); @@ -233,7 +234,11 @@ _setimage(ImagingEncoderObject* encoder, PyObject* args) /* Allocate memory buffer (if bits field is set) */ if (state->bits > 0) { + if (state->xsize > ((INT_MAX / state->bits)-7)) { + return PyErr_NoMemory(); + } state->bytes = (state->bits * state->xsize+7)/8; + /* malloc check ok, overflow checked above */ state->buffer = (UINT8*) malloc(state->bytes); if (!state->buffer) return PyErr_NoMemory(); @@ -478,10 +483,9 @@ PyImaging_ZipEncoderNew(PyObject* self, PyObject* args) &dictionary, &dictionary_size)) return NULL; - /* Copy to avoid referencing Python's memory, but there's no mechanism to - free this memory later, so this function (and several others here) - leaks. */ + /* Copy to avoid referencing Python's memory */ if (dictionary && dictionary_size > 0) { + /* malloc check ok, size comes from PyArg_ParseTuple */ char* p = malloc(dictionary_size); if (!p) return PyErr_NoMemory(); @@ -498,6 +502,7 @@ PyImaging_ZipEncoderNew(PyObject* self, PyObject* args) return NULL; encoder->encode = ImagingZipEncode; + encoder->cleanup = ImagingZipEncodeCleanup; if (rawmode[0] == 'P') /* disable filtering */ @@ -559,6 +564,7 @@ static unsigned int* get_qtables_arrays(PyObject* qtables, int* qtablesLen) { Py_DECREF(tables); return NULL; } + /* malloc check ok, num_tables <4, DCTSIZE2 == 64 from jpeglib.h */ qarrays = (unsigned int*) malloc(num_tables * DCTSIZE2 * sizeof(unsigned int)); if (!qarrays) { Py_DECREF(tables); @@ -631,9 +637,11 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args) if (get_packer(encoder, mode, rawmode) < 0) return NULL; + // Freed in JpegEncode, Case 5 qarrays = get_qtables_arrays(qtables, &qtablesLen); if (extra && extra_size > 0) { + /* malloc check ok, length is from python parsearg */ char* p = malloc(extra_size); // Freed in JpegEncode, Case 5 if (!p) return PyErr_NoMemory(); @@ -643,6 +651,7 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args) extra = NULL; if (rawExif && rawExifLen > 0) { + /* malloc check ok, length is from python parsearg */ char* pp = malloc(rawExifLen); // Freed in JpegEncode, Case 5 if (!pp) return PyErr_NoMemory(); @@ -757,15 +766,16 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args) (ttag_t) PyInt_AsLong(key), PyBytes_AsString(value)); } else if (PyTuple_Check(value)) { - int len,i; + Py_ssize_t len,i; float *floatav; int *intav; TRACE(("Setting from Tuple: %d \n", (int)PyInt_AsLong(key))); - len = (int)PyTuple_Size(value); + len = PyTuple_Size(value); if (len) { if (PyInt_Check(PyTuple_GetItem(value,0))) { - TRACE((" %d elements, setting as ints \n", len)); - intav = malloc(sizeof(int)*len); + TRACE((" %d elements, setting as ints \n", (int)len)); + /* malloc check ok, calloc checks for overflow */ + intav = calloc(len, sizeof(int)); if (intav) { for (i=0;iinfo = (BITMAPINFO*) malloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); if (!dib->info) { free(dib); - return (ImagingDIB) ImagingError_MemoryError(); + return (ImagingDIB) ImagingError_MemoryError(); } memset(dib->info, 0, sizeof(BITMAPINFOHEADER)); @@ -91,17 +93,17 @@ ImagingNewDIB(const char *mode, int xsize, int ysize) /* Create DIB */ dib->dc = CreateCompatibleDC(NULL); if (!dib->dc) { - free(dib->info); - free(dib); - return (ImagingDIB) ImagingError_MemoryError(); + free(dib->info); + free(dib); + return (ImagingDIB) ImagingError_MemoryError(); } dib->bitmap = CreateDIBSection(dib->dc, dib->info, DIB_RGB_COLORS, &dib->bits, NULL, 0); if (!dib->bitmap) { free(dib->info); - free(dib); - return (ImagingDIB) ImagingError_MemoryError(); + free(dib); + return (ImagingDIB) ImagingError_MemoryError(); } strcpy(dib->mode, mode); @@ -112,10 +114,10 @@ ImagingNewDIB(const char *mode, int xsize, int ysize) dib->linesize = (xsize * dib->pixelsize + 3) & -4; if (dib->pixelsize == 1) - dib->pack = dib->unpack = (ImagingShuffler) memcpy; + dib->pack = dib->unpack = (ImagingShuffler) memcpy; else { - dib->pack = ImagingPackBGR; - dib->unpack = ImagingPackBGR; + dib->pack = ImagingPackBGR; + dib->unpack = ImagingPackBGR; } /* Bind the DIB to the device context */ @@ -125,88 +127,88 @@ ImagingNewDIB(const char *mode, int xsize, int ysize) /* Bind a palette to it as well (only required for 8-bit DIBs) */ if (dib->pixelsize == 1) { - for (i = 0; i < 256; i++) { - palette[i].rgbRed = - palette[i].rgbGreen = - palette[i].rgbBlue = i; - palette[i].rgbReserved = 0; + for (i = 0; i < 256; i++) { + palette[i].rgbRed = + palette[i].rgbGreen = + palette[i].rgbBlue = i; + palette[i].rgbReserved = 0; } - SetDIBColorTable(dib->dc, 0, 256, palette); + SetDIBColorTable(dib->dc, 0, 256, palette); } /* Create an associated palette (for 8-bit displays only) */ if (strcmp(ImagingGetModeDIB(NULL), "P") == 0) { - char palbuf[sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY)]; - LPLOGPALETTE pal = (LPLOGPALETTE) palbuf; - int i, r, g, b; + char palbuf[sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY)]; + LPLOGPALETTE pal = (LPLOGPALETTE) palbuf; + int i, r, g, b; - /* Load system palette */ - pal->palVersion = 0x300; - pal->palNumEntries = 256; - GetSystemPaletteEntries(dib->dc, 0, 256, pal->palPalEntry); + /* Load system palette */ + pal->palVersion = 0x300; + pal->palNumEntries = 256; + GetSystemPaletteEntries(dib->dc, 0, 256, pal->palPalEntry); - if (strcmp(mode, "L") == 0) { + if (strcmp(mode, "L") == 0) { - /* Greyscale DIB. Fill all 236 slots with a greyscale ramp - * (this is usually overkill on Windows since VGA only offers - * 6 bits greyscale resolution). Ignore the slots already - * allocated by Windows */ + /* Greyscale DIB. Fill all 236 slots with a greyscale ramp + * (this is usually overkill on Windows since VGA only offers + * 6 bits greyscale resolution). Ignore the slots already + * allocated by Windows */ - i = 10; - for (r = 0; r < 236; r++) { - pal->palPalEntry[i].peRed = - pal->palPalEntry[i].peGreen = - pal->palPalEntry[i].peBlue = i; - i++; - } + i = 10; + for (r = 0; r < 236; r++) { + pal->palPalEntry[i].peRed = + pal->palPalEntry[i].peGreen = + pal->palPalEntry[i].peBlue = i; + i++; + } - dib->palette = CreatePalette(pal); + dib->palette = CreatePalette(pal); - } else if (strcmp(mode, "RGB") == 0) { + } else if (strcmp(mode, "RGB") == 0) { #ifdef CUBE216 - /* Colour DIB. Create a 6x6x6 colour cube (216 entries) and - * add 20 extra greylevels for best result with greyscale - * images. */ + /* Colour DIB. Create a 6x6x6 colour cube (216 entries) and + * add 20 extra greylevels for best result with greyscale + * images. */ - i = 10; - for (r = 0; r < 256; r += 51) - for (g = 0; g < 256; g += 51) - for (b = 0; b < 256; b += 51) { - pal->palPalEntry[i].peRed = r; - pal->palPalEntry[i].peGreen = g; - pal->palPalEntry[i].peBlue = b; - i++; - } - for (r = 1; r < 22-1; r++) { - /* Black and white are already provided by the cube. */ - pal->palPalEntry[i].peRed = - pal->palPalEntry[i].peGreen = - pal->palPalEntry[i].peBlue = r * 255 / (22-1); - i++; - } + i = 10; + for (r = 0; r < 256; r += 51) + for (g = 0; g < 256; g += 51) + for (b = 0; b < 256; b += 51) { + pal->palPalEntry[i].peRed = r; + pal->palPalEntry[i].peGreen = g; + pal->palPalEntry[i].peBlue = b; + i++; + } + for (r = 1; r < 22-1; r++) { + /* Black and white are already provided by the cube. */ + pal->palPalEntry[i].peRed = + pal->palPalEntry[i].peGreen = + pal->palPalEntry[i].peBlue = r * 255 / (22-1); + i++; + } #else - /* Colour DIB. Alternate palette. */ + /* Colour DIB. Alternate palette. */ - i = 10; - for (r = 0; r < 256; r += 37) - for (g = 0; g < 256; g += 32) - for (b = 0; b < 256; b += 64) { - pal->palPalEntry[i].peRed = r; - pal->palPalEntry[i].peGreen = g; - pal->palPalEntry[i].peBlue = b; - i++; - } + i = 10; + for (r = 0; r < 256; r += 37) + for (g = 0; g < 256; g += 32) + for (b = 0; b < 256; b += 64) { + pal->palPalEntry[i].peRed = r; + pal->palPalEntry[i].peGreen = g; + pal->palPalEntry[i].peBlue = b; + i++; + } #endif - dib->palette = CreatePalette(pal); + dib->palette = CreatePalette(pal); - } + } } @@ -222,8 +224,8 @@ ImagingPasteDIB(ImagingDIB dib, Imaging im, int xy[4]) int y; for (y = 0; y < im->ysize; y++) - dib->pack(dib->bits + dib->linesize*(dib->ysize-(xy[1]+y)-1) + - xy[0]*dib->pixelsize, im->image[y], im->xsize); + dib->pack(dib->bits + dib->linesize*(dib->ysize-(xy[1]+y)-1) + + xy[0]*dib->pixelsize, im->image[y], im->xsize); } @@ -233,7 +235,7 @@ ImagingExposeDIB(ImagingDIB dib, void *dc) /* Copy bitmap to display */ if (dib->palette != 0) - SelectPalette((HDC) dc, dib->palette, FALSE); + SelectPalette((HDC) dc, dib->palette, FALSE); BitBlt((HDC) dc, 0, 0, dib->xsize, dib->ysize, dib->dc, 0, 0, SRCCOPY); } @@ -266,15 +268,15 @@ ImagingQueryPaletteDIB(ImagingDIB dib, void *dc) if (dib->palette != 0) { - /* Realize associated palette */ - HPALETTE now = SelectPalette((HDC) dc, dib->palette, FALSE); - n = RealizePalette((HDC) dc); + /* Realize associated palette */ + HPALETTE now = SelectPalette((HDC) dc, dib->palette, FALSE); + n = RealizePalette((HDC) dc); - /* Restore palette */ - SelectPalette((HDC) dc, now, FALSE); + /* Restore palette */ + SelectPalette((HDC) dc, now, FALSE); } else - n = 0; + n = 0; return n; /* number of colours that was changed */ } @@ -285,13 +287,13 @@ ImagingDeleteDIB(ImagingDIB dib) /* Clean up */ if (dib->palette) - DeleteObject(dib->palette); + DeleteObject(dib->palette); if (dib->bitmap) { SelectObject(dib->dc, dib->old_bitmap); - DeleteObject(dib->bitmap); + DeleteObject(dib->bitmap); } if (dib->dc) - DeleteDC(dib->dc); + DeleteDC(dib->dc); free(dib->info); } diff --git a/libImaging/Draw.c b/libImaging/Draw.c index 423f1bea2..ef3f54dc0 100644 --- a/libImaging/Draw.c +++ b/libImaging/Draw.c @@ -434,7 +434,8 @@ polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, } /* Initialize the edge table and find polygon boundaries */ - edge_table = malloc(sizeof(Edge*) * n); + /* malloc check ok, using calloc */ + edge_table = calloc(n, sizeof(Edge*)); if (!edge_table) { return -1; } @@ -462,7 +463,8 @@ polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, } /* Process the edge table with a scan line searching for intersections */ - xx = malloc(sizeof(float) * edge_count * 2); + /* malloc check ok, using calloc */ + xx = calloc(edge_count * 2, sizeof(float)); if (!xx) { free(edge_table); return -1; @@ -700,7 +702,8 @@ ImagingDrawPolygon(Imaging im, int count, int* xy, const void* ink_, if (fill) { /* Build edge list */ - Edge* e = malloc(count * sizeof(Edge)); + /* malloc check ok, using calloc */ + Edge* e = calloc(count, sizeof(Edge)); if (!e) { (void) ImagingError_MemoryError(); return -1; @@ -769,10 +772,16 @@ ellipse(Imaging im, int x0, int y0, int x1, int y1, while (end < start) end += 360; + if (end - start > 360) { + /* no need to go in loops */ + end = start + 361; + } + if (mode != ARC && fill) { /* Build edge list */ - Edge* e = malloc((end - start + 3) * sizeof(Edge)); + /* malloc check UNDONE, FLOAT? */ + Edge* e = calloc((end - start + 3), sizeof(Edge)); if (!e) { ImagingError_MemoryError(); return -1; @@ -929,10 +938,16 @@ allocate(ImagingOutline outline, int extra) if (outline->count + extra > outline->size) { /* expand outline buffer */ outline->size += extra + 25; - if (!outline->edges) - e = malloc(outline->size * sizeof(Edge)); - else + if (!outline->edges) { + /* malloc check ok, uses calloc for overflow */ + e = calloc(outline->size, sizeof(Edge)); + } else { + if (outline->size > INT_MAX / sizeof(Edge)) { + return NULL; + } + /* malloc check ok, overflow checked above */ e = realloc(outline->edges, outline->size * sizeof(Edge)); + } if (!e) return NULL; outline->edges = e; diff --git a/libImaging/Geometry.c b/libImaging/Geometry.c index 103b75e53..a11a4eac1 100644 --- a/libImaging/Geometry.c +++ b/libImaging/Geometry.c @@ -683,8 +683,9 @@ ImagingScaleAffine(Imaging imOut, Imaging imIn, x1 = imOut->xsize; if (y1 > imOut->ysize) y1 = imOut->ysize; - - xintab = (int*) malloc(imOut->xsize * sizeof(int)); + + /* malloc check ok, uses calloc for overflow */ + xintab = (int*) calloc(imOut->xsize, sizeof(int)); if (!xintab) { ImagingDelete(imOut); return (Imaging) ImagingError_MemoryError(); diff --git a/libImaging/GifEncode.c b/libImaging/GifEncode.c index 4ada55496..f211814ed 100644 --- a/libImaging/GifEncode.c +++ b/libImaging/GifEncode.c @@ -61,6 +61,7 @@ emit(GIFENCODERSTATE *context, int byte) block = context->free; context->free = NULL; } else { + /* malloc check ok, small constant allocation */ block = malloc(sizeof(GIFENCODERBLOCK)); if (!block) return 0; diff --git a/libImaging/Imaging.h b/libImaging/Imaging.h index cdda4ae40..d0c59c9d0 100644 --- a/libImaging/Imaging.h +++ b/libImaging/Imaging.h @@ -168,9 +168,9 @@ extern Imaging ImagingNewMap(const char* filename, int readonly, const char* mode, int xsize, int ysize); extern Imaging ImagingNewPrologue(const char *mode, - unsigned xsize, unsigned ysize); + int xsize, int ysize); extern Imaging ImagingNewPrologueSubtype(const char *mode, - unsigned xsize, unsigned ysize, + int xsize, int ysize, int structure_size); extern Imaging ImagingNewEpilogue(Imaging im); @@ -453,6 +453,7 @@ extern int ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buffer, int bytes); extern int ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buffer, int bytes); +extern int ImagingZipEncodeCleanup(ImagingCodecState state); #endif typedef void (*ImagingShuffler)(UINT8* out, const UINT8* in, int pixels); diff --git a/libImaging/Incremental.c b/libImaging/Incremental.c index f34765423..f0e55244c 100644 --- a/libImaging/Incremental.c +++ b/libImaging/Incremental.c @@ -168,6 +168,7 @@ ImagingIncrementalCodecCreate(ImagingIncrementalCodecEntry codec_entry, int seekable, int fd) { + /* malloc check ok, small constant allocation */ ImagingIncrementalCodec codec = (ImagingIncrementalCodec)malloc(sizeof(struct ImagingIncrementalCodecStruct)); codec->entry = codec_entry; @@ -370,7 +371,17 @@ ImagingIncrementalCodecPushBuffer(ImagingIncrementalCodec codec, /* In this specific case, we append to a buffer we allocate ourselves */ size_t old_size = codec->stream.end - codec->stream.buffer; size_t new_size = codec->stream.end - codec->stream.buffer + bytes; - UINT8 *new = (UINT8 *)realloc (codec->stream.buffer, new_size); + UINT8 *new; + + if (old_size > SIZE_MAX - bytes) { + codec->state->errcode = IMAGING_CODEC_MEMORY; +#ifndef _WIN32 + pthread_mutex_unlock(&codec->data_mutex); +#endif + return -1; + } + /* malloc check ok, overflow checked */ + new = (UINT8 *)realloc (codec->stream.buffer, new_size); if (!new) { codec->state->errcode = IMAGING_CODEC_MEMORY; diff --git a/libImaging/Jpeg2KDecode.c b/libImaging/Jpeg2KDecode.c index 07bee2b5e..239461c7c 100644 --- a/libImaging/Jpeg2KDecode.c +++ b/libImaging/Jpeg2KDecode.c @@ -702,6 +702,7 @@ j2k_decode_entry(Imaging im, ImagingCodecState state, tile_info.y1 = (tile_info.y1 + correction) >> context->reduce; if (buffer_size < tile_info.data_size) { + /* malloc check ok, tile_info.data_size from openjpeg */ UINT8 *new = realloc (state->buffer, tile_info.data_size); if (!new) { state->errcode = IMAGING_CODEC_MEMORY; diff --git a/libImaging/Palette.c b/libImaging/Palette.c index 9b0dd57c4..31c2c0245 100644 --- a/libImaging/Palette.c +++ b/libImaging/Palette.c @@ -31,20 +31,20 @@ ImagingPaletteNew(const char* mode) ImagingPalette palette; if (strcmp(mode, "RGB") && strcmp(mode, "RGBA")) - return (ImagingPalette) ImagingError_ModeError(); + return (ImagingPalette) ImagingError_ModeError(); palette = calloc(1, sizeof(struct ImagingPaletteInstance)); if (!palette) - return (ImagingPalette) ImagingError_MemoryError(); + return (ImagingPalette) ImagingError_MemoryError(); strncpy(palette->mode, mode, IMAGING_MODE_LENGTH); /* Initialize to ramp */ for (i = 0; i < 256; i++) { - palette->palette[i*4+0] = - palette->palette[i*4+1] = - palette->palette[i*4+2] = (UINT8) i; - palette->palette[i*4+3] = 255; /* opaque */ + palette->palette[i*4+0] = + palette->palette[i*4+1] = + palette->palette[i*4+2] = (UINT8) i; + palette->palette[i*4+3] = 255; /* opaque */ } return palette; @@ -60,35 +60,35 @@ ImagingPaletteNewBrowser(void) palette = ImagingPaletteNew("RGB"); if (!palette) - return NULL; + return NULL; /* Blank out unused entries */ /* FIXME: Add 10-level windows palette here? */ for (i = 0; i < 10; i++) { - palette->palette[i*4+0] = - palette->palette[i*4+1] = - palette->palette[i*4+2] = 0; + palette->palette[i*4+0] = + palette->palette[i*4+1] = + palette->palette[i*4+2] = 0; } /* Simple 6x6x6 colour cube */ for (b = 0; b < 256; b += 51) - for (g = 0; g < 256; g += 51) - for (r = 0; r < 256; r += 51) { - palette->palette[i*4+0] = r; - palette->palette[i*4+1] = g; - palette->palette[i*4+2] = b; - i++; - } + for (g = 0; g < 256; g += 51) + for (r = 0; r < 256; r += 51) { + palette->palette[i*4+0] = r; + palette->palette[i*4+1] = g; + palette->palette[i*4+2] = b; + i++; + } /* Blank out unused entries */ /* FIXME: add 30-level greyscale wedge here? */ for (; i < 256; i++) { - palette->palette[i*4+0] = - palette->palette[i*4+1] = - palette->palette[i*4+2] = 0; + palette->palette[i*4+0] = + palette->palette[i*4+1] = + palette->palette[i*4+2] = 0; } return palette; @@ -102,11 +102,11 @@ ImagingPaletteDuplicate(ImagingPalette palette) ImagingPalette new_palette; if (!palette) - return NULL; - + return NULL; + /* malloc check ok, small constant allocation */ new_palette = malloc(sizeof(struct ImagingPaletteInstance)); if (!new_palette) - return (ImagingPalette) ImagingError_MemoryError(); + return (ImagingPalette) ImagingError_MemoryError(); memcpy(new_palette, palette, sizeof(struct ImagingPaletteInstance)); @@ -122,15 +122,15 @@ ImagingPaletteDelete(ImagingPalette palette) /* Destroy palette object */ if (palette) { - if (palette->cache) - free(palette->cache); - free(palette); + if (palette->cache) + free(palette->cache); + free(palette); } } /* -------------------------------------------------------------------- */ -/* Colour mapping */ +/* Colour mapping */ /* -------------------------------------------------------------------- */ /* This code is used to map RGB triplets to palette indices, using @@ -143,26 +143,26 @@ ImagingPaletteDelete(ImagingPalette palette) * * The IJG JPEG library is copyright (C) 1991-1995, Thomas G. Lane. */ -#define DIST(a, b, s) (a - b) * (a - b) * s +#define DIST(a, b, s) (a - b) * (a - b) * s /* Colour weights (no scaling, for now) */ -#define RSCALE 1 -#define GSCALE 1 -#define BSCALE 1 +#define RSCALE 1 +#define GSCALE 1 +#define BSCALE 1 /* Calculated scaled distances */ -#define RDIST(a, b) DIST(a, b, RSCALE*RSCALE) -#define GDIST(a, b) DIST(a, b, GSCALE*GSCALE) -#define BDIST(a, b) DIST(a, b, BSCALE*BSCALE) +#define RDIST(a, b) DIST(a, b, RSCALE*RSCALE) +#define GDIST(a, b) DIST(a, b, GSCALE*GSCALE) +#define BDIST(a, b) DIST(a, b, BSCALE*BSCALE) /* Incremental steps */ -#define RSTEP (4 * RSCALE) -#define GSTEP (4 * GSCALE) -#define BSTEP (4 * BSCALE) +#define RSTEP (4 * RSCALE) +#define GSTEP (4 * GSCALE) +#define BSTEP (4 * BSCALE) -#define BOX 8 +#define BOX 8 -#define BOXVOLUME BOX*BOX*BOX +#define BOXVOLUME BOX*BOX*BOX void ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b) @@ -191,25 +191,25 @@ ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b) for (i = 0; i < 256; i++) { - int r, g, b; - unsigned int tmin, tmax; + int r, g, b; + unsigned int tmin, tmax; - /* Find min and max distances to any point in the box */ - r = palette->palette[i*4+0]; - tmin = (r < r0) ? RDIST(r, r1) : (r > r1) ? RDIST(r, r0) : 0; - tmax = (r <= rc) ? RDIST(r, r1) : RDIST(r, r0); + /* Find min and max distances to any point in the box */ + r = palette->palette[i*4+0]; + tmin = (r < r0) ? RDIST(r, r1) : (r > r1) ? RDIST(r, r0) : 0; + tmax = (r <= rc) ? RDIST(r, r1) : RDIST(r, r0); - g = palette->palette[i*4+1]; - tmin += (g < g0) ? GDIST(g, g1) : (g > g1) ? GDIST(g, g0) : 0; - tmax += (g <= gc) ? GDIST(g, g1) : GDIST(g, g0); + g = palette->palette[i*4+1]; + tmin += (g < g0) ? GDIST(g, g1) : (g > g1) ? GDIST(g, g0) : 0; + tmax += (g <= gc) ? GDIST(g, g1) : GDIST(g, g0); - b = palette->palette[i*4+2]; - tmin += (b < b0) ? BDIST(b, b1) : (b > b1) ? BDIST(b, b0) : 0; - tmax += (b <= bc) ? BDIST(b, b1) : BDIST(b, b0); + b = palette->palette[i*4+2]; + tmin += (b < b0) ? BDIST(b, b1) : (b > b1) ? BDIST(b, b0) : 0; + tmax += (b <= bc) ? BDIST(b, b1) : BDIST(b, b0); - dmin[i] = tmin; - if (tmax < dmax) - dmax = tmax; /* keep the smallest max distance only */ + dmin[i] = tmin; + if (tmax < dmax) + dmax = tmax; /* keep the smallest max distance only */ } @@ -220,47 +220,47 @@ ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b) * distance is less than or equal the smallest max distance */ for (i = 0; i < BOXVOLUME; i++) - d[i] = (unsigned int) ~0; + d[i] = (unsigned int) ~0; for (i = 0; i < 256; i++) - if (dmin[i] <= dmax) { + if (dmin[i] <= dmax) { - int rd, gd, bd; - int ri, gi, bi; - int rx, gx, bx; + int rd, gd, bd; + int ri, gi, bi; + int rx, gx, bx; - ri = (r0 - palette->palette[i*4+0]) * RSCALE; - gi = (g0 - palette->palette[i*4+1]) * GSCALE; - bi = (b0 - palette->palette[i*4+2]) * BSCALE; + ri = (r0 - palette->palette[i*4+0]) * RSCALE; + gi = (g0 - palette->palette[i*4+1]) * GSCALE; + bi = (b0 - palette->palette[i*4+2]) * BSCALE; - rd = ri*ri + gi*gi + bi*bi; + rd = ri*ri + gi*gi + bi*bi; - ri = ri * (2 * RSTEP) + RSTEP * RSTEP; - gi = gi * (2 * GSTEP) + GSTEP * GSTEP; - bi = bi * (2 * BSTEP) + BSTEP * BSTEP; + ri = ri * (2 * RSTEP) + RSTEP * RSTEP; + gi = gi * (2 * GSTEP) + GSTEP * GSTEP; + bi = bi * (2 * BSTEP) + BSTEP * BSTEP; - rx = ri; - for (r = j = 0; r < BOX; r++) { - gd = rd; gx = gi; - for (g = 0; g < BOX; g++) { - bd = gd; bx = bi; - for (b = 0; b < BOX; b++) { - if ((unsigned int) bd < d[j]) { - d[j] = bd; - c[j] = (UINT8) i; - } - bd += bx; - bx += 2 * BSTEP * BSTEP; - j++; - } - gd += gx; - gx += 2 * GSTEP * GSTEP; - } - rd += rx; - rx += 2 * RSTEP * RSTEP; - } - } + rx = ri; + for (r = j = 0; r < BOX; r++) { + gd = rd; gx = gi; + for (g = 0; g < BOX; g++) { + bd = gd; bx = bi; + for (b = 0; b < BOX; b++) { + if ((unsigned int) bd < d[j]) { + d[j] = bd; + c[j] = (UINT8) i; + } + bd += bx; + bx += 2 * BSTEP * BSTEP; + j++; + } + gd += gx; + gx += 2 * GSTEP * GSTEP; + } + rd += rx; + rx += 2 * RSTEP * RSTEP; + } + } /* Step 3 -- Update cache */ @@ -269,9 +269,9 @@ ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b) j = 0; for (r = r0; r < r1; r+=4) - for (g = g0; g < g1; g+=4) - for (b = b0; b < b1; b+=4) - ImagingPaletteCache(palette, r, g, b) = c[j++]; + for (g = g0; g < g1; g+=4) + for (b = b0; b < b1; b+=4) + ImagingPaletteCache(palette, r, g, b) = c[j++]; } @@ -285,18 +285,19 @@ ImagingPaletteCachePrepare(ImagingPalette palette) if (palette->cache == NULL) { - /* The cache is 512k. It might be a good idea to break it - up into a pointer array (e.g. an 8-bit image?) */ + /* The cache is 512k. It might be a good idea to break it + up into a pointer array (e.g. an 8-bit image?) */ - palette->cache = (INT16*) malloc(entries * sizeof(INT16)); - if (!palette->cache) { - (void) ImagingError_MemoryError(); - return -1; - } + /* malloc check ok, small constant allocation */ + palette->cache = (INT16*) malloc(entries * sizeof(INT16)); + if (!palette->cache) { + (void) ImagingError_MemoryError(); + return -1; + } - /* Mark all entries as empty */ - for (i = 0; i < entries; i++) - palette->cache[i] = 0x100; + /* Mark all entries as empty */ + for (i = 0; i < entries; i++) + palette->cache[i] = 0x100; } @@ -310,7 +311,7 @@ ImagingPaletteCacheDelete(ImagingPalette palette) /* Release the colour cache, if any */ if (palette && palette->cache) { - free(palette->cache); - palette->cache = NULL; + free(palette->cache); + palette->cache = NULL; } } diff --git a/libImaging/Quant.c b/libImaging/Quant.c index 6c122eee2..f041451be 100644 --- a/libImaging/Quant.c +++ b/libImaging/Quant.c @@ -31,6 +31,11 @@ #include "QuantHash.h" #include "QuantHeap.h" +/* MSVC9.0 */ +#ifndef UINT32_MAX +#define UINT32_MAX 0xffffffff +#endif + #define NO_OUTPUT typedef struct { @@ -150,6 +155,7 @@ create_pixel_hash(Pixel *pixelData,uint32_t nPixels) uint32_t timer,timer2,timer3; #endif + /* malloc check ok, small constant allocation */ d=malloc(sizeof(PixelHashData)); if (!d) return NULL; hash=hashtable_new(pixel_hash,pixel_cmp); @@ -234,6 +240,7 @@ hash_to_list(const HashTable *h, const Pixel pixel, const uint32_t count, void * PIXEL_SCALE(&pixel,&q,d->scale); + /* malloc check ok, small constant allocation */ p=malloc(sizeof(PixelList)); if (!p) return; @@ -557,6 +564,7 @@ split(BoxNode *node) exit(1); } #endif + /* malloc check ok, small constant allocation */ left=malloc(sizeof(BoxNode)); right=malloc(sizeof(BoxNode)); if (!left||!right) { @@ -613,6 +621,7 @@ median_cut(PixelList *hl[3], BoxNode *thisNode; h=ImagingQuantHeapNew(box_heap_cmp); + /* malloc check ok, small constant allocation */ root=malloc(sizeof(BoxNode)); if (!root) { ImagingQuantHeapFree(h); return NULL; } for(i=0;i<3;i++) { @@ -954,15 +963,16 @@ compute_palette_from_median_cut( uint32_t *count; *palette=NULL; - if (!(count=malloc(sizeof(uint32_t)*nPaletteEntries))) { + /* malloc check ok, using calloc */ + if (!(count=calloc(nPaletteEntries, sizeof(uint32_t)))) { return 0; } - memset(count,0,sizeof(uint32_t)*nPaletteEntries); for(i=0;i<3;i++) { avg[i]=NULL; } for(i=0;i<3;i++) { - if (!(avg[i]=malloc(sizeof(uint32_t)*nPaletteEntries))) { + /* malloc check ok, using calloc */ + if (!(avg[i]=calloc(nPaletteEntries, sizeof(uint32_t)))) { for(i=0;i<3;i++) { if (avg[i]) free (avg[i]); } @@ -970,9 +980,6 @@ compute_palette_from_median_cut( return 0; } } - for(i=0;i<3;i++) { - memset(avg[i],0,sizeof(uint32_t)*nPaletteEntries); - } for (i=0;i UINT32_MAX / (sizeof(uint32_t))) { + return 0; + } + /* malloc check ok, using calloc */ + if (!(count=calloc(nPaletteEntries, sizeof(uint32_t)))) { return 0; } for(i=0;i<3;i++) { avg[i]=NULL; } for(i=0;i<3;i++) { - if (!(avg[i]=malloc(sizeof(uint32_t)*nPaletteEntries))) { + /* malloc check ok, using calloc */ + if (!(avg[i]=calloc(nPaletteEntries, sizeof(uint32_t)))) { goto error_1; } } - avgDist=malloc(sizeof(uint32_t)*nPaletteEntries*nPaletteEntries); + + /* this is enough of a check, since the multiplication n*size is done above */ + if (nPaletteEntries > UINT32_MAX / nPaletteEntries) { + goto error_1; + } + /* malloc check ok, using calloc, checking n*n above */ + avgDist=calloc(nPaletteEntries*nPaletteEntries, sizeof(uint32_t)); if (!avgDist) { goto error_1; } - avgDistSortKey=malloc(sizeof(uint32_t *)*nPaletteEntries*nPaletteEntries); + /* malloc check ok, using calloc, checking n*n above */ + avgDistSortKey=calloc(nPaletteEntries*nPaletteEntries, sizeof(uint32_t *)); if (!avgDistSortKey) { goto error_2; } #ifndef NO_OUTPUT @@ -1251,13 +1271,19 @@ quantize(Pixel *pixelData, free_box_tree(root); root=NULL; - qp=malloc(sizeof(uint32_t)*nPixels); + /* malloc check ok, using calloc for overflow */ + qp=calloc(nPixels, sizeof(uint32_t)); if (!qp) { goto error_4; } - avgDist=malloc(sizeof(uint32_t)*nPaletteEntries*nPaletteEntries); + if (nPaletteEntries > UINT32_MAX / nPaletteEntries ) { + goto error_5; + } + /* malloc check ok, using calloc for overflow, check of n*n above */ + avgDist=calloc(nPaletteEntries*nPaletteEntries, sizeof(uint32_t)); if (!avgDist) { goto error_5; } - avgDistSortKey=malloc(sizeof(uint32_t *)*nPaletteEntries*nPaletteEntries); + /* malloc check ok, using calloc for overflow, check of n*n above */ + avgDistSortKey=calloc(nPaletteEntries*nPaletteEntries, sizeof(uint32_t *)); if (!avgDistSortKey) { goto error_6; } if (!build_distance_tables(avgDist,avgDistSortKey,p,nPaletteEntries)) { @@ -1399,8 +1425,9 @@ quantize2(Pixel *pixelData, uint32_t *qp; uint32_t *avgDist; uint32_t **avgDistSortKey; - - p=malloc(sizeof(Pixel)*nQuantPixels); + + /* malloc check ok, using calloc */ + p=calloc(nQuantPixels, sizeof(Pixel)); if (!p) return 0; mean[0]=mean[1]=mean[2]=0; h=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp); @@ -1422,13 +1449,20 @@ quantize2(Pixel *pixelData, } hashtable_free(h); - qp=malloc(sizeof(uint32_t)*nPixels); + /* malloc check ok, using calloc */ + qp=calloc(nPixels, sizeof(uint32_t)); if (!qp) { goto error_1; } - avgDist=malloc(sizeof(uint32_t)*nQuantPixels*nQuantPixels); + if (nQuantPixels > UINT32_MAX / nQuantPixels ) { + goto error_2; + } + + /* malloc check ok, using calloc for overflow, check of n*n above */ + avgDist=calloc(nQuantPixels*nQuantPixels, sizeof(uint32_t)); if (!avgDist) { goto error_2; } - avgDistSortKey=malloc(sizeof(uint32_t *)*nQuantPixels*nQuantPixels); + /* malloc check ok, using calloc for overflow, check of n*n above */ + avgDistSortKey=calloc(nQuantPixels*nQuantPixels, sizeof(uint32_t *)); if (!avgDistSortKey) { goto error_3; } if (!build_distance_tables(avgDist,avgDistSortKey,p,nQuantPixels)) { @@ -1474,7 +1508,7 @@ ImagingQuantize(Imaging im, int colors, int mode, int kmeans) ImagingSectionCookie cookie; if (!im) - return ImagingError_ModeError(); + return ImagingError_ModeError(); if (colors < 1 || colors > 256) /* FIXME: for colors > 256, consider returning an RGB image instead (see @PIL205) */ @@ -1488,7 +1522,11 @@ ImagingQuantize(Imaging im, int colors, int mode, int kmeans) if (!strcmp(im->mode, "RGBA") && mode != 2 && mode != 3) return ImagingError_ModeError(); - p = malloc(sizeof(Pixel) * im->xsize * im->ysize); + if (im->xsize > INT_MAX / im->ysize) { + return ImagingError_MemoryError(); + } + /* malloc check ok, using calloc for final overflow, x*y above */ + p = calloc(im->xsize * im->ysize, sizeof(Pixel)); if (!p) return ImagingError_MemoryError(); diff --git a/libImaging/QuantHeap.c b/libImaging/QuantHeap.c index 9006903b7..2a4a5adc0 100644 --- a/libImaging/QuantHeap.c +++ b/libImaging/QuantHeap.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "QuantHeap.h" @@ -47,7 +48,12 @@ static int _heap_grow(Heap *h,int newsize) { void *newheap; if (!newsize) newsize=h->heapsize<<1; if (newsizeheapsize) return 0; - newheap=malloc(sizeof(void *)*newsize); + if (newsize > INT_MAX / sizeof(void *)){ + return 0; + } + /* malloc check ok, using calloc for overflow, also checking + above due to memcpy below*/ + newheap=calloc(newsize, sizeof(void *)); if (!newheap) return 0; memcpy(newheap,h->heap,sizeof(void *)*h->heapsize); free(h->heap); @@ -131,12 +137,17 @@ int ImagingQuantHeapTop(Heap *h,void **r) { Heap *ImagingQuantHeapNew(HeapCmpFunc cf) { Heap *h; - + + /* malloc check ok, small constant allocation */ h=malloc(sizeof(Heap)); if (!h) return NULL; h->heapsize=INITIAL_SIZE; - h->heap=malloc(sizeof(void *)*h->heapsize); - if (!h->heap) { free(h); return NULL; } + /* malloc check ok, using calloc for overflow */ + h->heap=calloc(h->heapsize, sizeof(void *)); + if (!h->heap) { + free(h); + return NULL; + } h->heapcount=0; h->cf=cf; return h; diff --git a/libImaging/QuantOctree.c b/libImaging/QuantOctree.c index cd0d7fbd1..ede3ad634 100644 --- a/libImaging/QuantOctree.c +++ b/libImaging/QuantOctree.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "QuantOctree.h" @@ -53,6 +54,7 @@ static ColorCube new_color_cube(int r, int g, int b, int a) { ColorCube cube; + /* malloc check ok, small constant allocation */ cube = malloc(sizeof(struct _ColorCube)); if (!cube) return NULL; @@ -61,6 +63,12 @@ new_color_cube(int r, int g, int b, int a) { cube->bBits = MAX(b, 0); cube->aBits = MAX(a, 0); + /* overflow check for size multiplication below */ + if (cube->rBits + cube->gBits + cube->bBits + cube->aBits > 31) { + free(cube); + return NULL; + } + /* the width of the cube for each dimension */ cube->rWidth = 1<rBits; cube->gWidth = 1<gBits; @@ -76,6 +84,7 @@ new_color_cube(int r, int g, int b, int a) { /* the number of color buckets */ cube->size = cube->rWidth * cube->gWidth * cube->bWidth * cube->aWidth; + /* malloc check ok, overflow checked above */ cube->buckets = calloc(cube->size, sizeof(struct _ColorBucket)); if (!cube->buckets) { @@ -154,7 +163,11 @@ compare_bucket_count(const ColorBucket a, const ColorBucket b) { static ColorBucket create_sorted_color_palette(const ColorCube cube) { ColorBucket buckets; - buckets = malloc(sizeof(struct _ColorBucket)*cube->size); + if (cube->size > LONG_MAX / sizeof(struct _ColorBucket)) { + return NULL; + } + /* malloc check ok, calloc + overflow check above for memcpy */ + buckets = calloc(cube->size, sizeof(struct _ColorBucket)); if (!buckets) return NULL; memcpy(buckets, cube->buckets, sizeof(struct _ColorBucket)*cube->size); @@ -280,7 +293,15 @@ void add_lookup_buckets(ColorCube cube, ColorBucket palette, long nColors, long ColorBucket combined_palette(ColorBucket bucketsA, long nBucketsA, ColorBucket bucketsB, long nBucketsB) { ColorBucket result; - result = malloc(sizeof(struct _ColorBucket)*(nBucketsA+nBucketsB)); + if (nBucketsA > LONG_MAX - nBucketsB || + (nBucketsA+nBucketsB) > LONG_MAX / sizeof(struct _ColorBucket)) { + return NULL; + } + /* malloc check ok, overflow check above */ + result = calloc(nBucketsA + nBucketsB, sizeof(struct _ColorBucket)); + if (!result) { + return NULL; + } memcpy(result, bucketsA, sizeof(struct _ColorBucket) * nBucketsA); memcpy(&result[nBucketsA], bucketsB, sizeof(struct _ColorBucket) * nBucketsB); return result; @@ -290,8 +311,9 @@ static Pixel * create_palette_array(const ColorBucket palette, unsigned int paletteLength) { Pixel *paletteArray; unsigned int i; - - paletteArray = malloc(sizeof(Pixel)*paletteLength); + + /* malloc check ok, calloc for overflow */ + paletteArray = calloc(paletteLength, sizeof(Pixel)); if (!paletteArray) return NULL; for (i=0; ibands != 1 || im->type == IMAGING_TYPE_SPECIAL) - return (Imaging) ImagingError_ModeError(); + return (Imaging) ImagingError_ModeError(); if (!(size & 1)) - return (Imaging) ImagingError_ValueError("bad filter size"); + return (Imaging) ImagingError_ValueError("bad filter size"); + + /* malloc check ok, for overflow in the define below */ + if (size > INT_MAX / size || + size > INT_MAX / (size * sizeof(FLOAT32))) { + return (Imaging) ImagingError_ValueError("filter size too large"); + } size2 = size * size; margin = (size-1) / 2; if (rank < 0 || rank >= size2) - return (Imaging) ImagingError_ValueError("bad rank value"); + return (Imaging) ImagingError_ValueError("bad rank value"); imOut = ImagingNew(im->mode, im->xsize - 2*margin, im->ysize - 2*margin); if (!imOut) - return NULL; + return NULL; + /* malloc check ok, checked above */ #define RANK_BODY(type) do {\ type* buf = malloc(size2 * sizeof(type));\ if (!buf)\ diff --git a/libImaging/Resample.c b/libImaging/Resample.c index 23e39a2e4..92caa748f 100644 --- a/libImaging/Resample.c +++ b/libImaging/Resample.c @@ -98,15 +98,13 @@ ImagingPrecompute(int inSize, int outSize, struct filter *filterp, if (outSize > INT_MAX / (kmax * sizeof(double))) return 0; - // sizeof(double) should be greater than 0 as well - if (outSize > INT_MAX / (2 * sizeof(double))) - return 0; - /* coefficient buffer */ + /* malloc check ok, overflow checked above */ kk = malloc(outSize * kmax * sizeof(double)); if ( ! kk) return 0; + /* malloc check ok, kmax*sizeof(double) > 2*sizeof(int) */ xbounds = malloc(outSize * 2 * sizeof(int)); if ( ! xbounds) { free(kk); diff --git a/libImaging/Storage.c b/libImaging/Storage.c index 4450d14e4..f40840671 100644 --- a/libImaging/Storage.c +++ b/libImaging/Storage.c @@ -46,7 +46,7 @@ int ImagingNewCount = 0; */ Imaging -ImagingNewPrologueSubtype(const char *mode, unsigned xsize, unsigned ysize, +ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size) { Imaging im; @@ -56,6 +56,11 @@ ImagingNewPrologueSubtype(const char *mode, unsigned xsize, unsigned ysize, if (!im) return (Imaging) ImagingError_MemoryError(); + /* linesize overflow check, roughly the current largest space req'd */ + if (xsize > (INT_MAX / 4) - 1) { + return (Imaging) ImagingError_MemoryError(); + } + /* Setup image descriptor */ im->xsize = xsize; im->ysize = ysize; @@ -226,7 +231,7 @@ ImagingNewPrologueSubtype(const char *mode, unsigned xsize, unsigned ysize, } Imaging -ImagingNewPrologue(const char *mode, unsigned xsize, unsigned ysize) +ImagingNewPrologue(const char *mode, int xsize, int ysize) { return ImagingNewPrologueSubtype( mode, xsize, ysize, sizeof(struct ImagingMemoryInstance) @@ -306,7 +311,8 @@ ImagingNewArray(const char *mode, int xsize, int ysize) /* Allocate image as an array of lines */ for (y = 0; y < im->ysize; y++) { - p = (char *) malloc(im->linesize); + /* malloc check linesize checked in prologue */ + p = (char *) calloc(1, im->linesize); if (!p) { ImagingDestroyArray(im); break; @@ -339,24 +345,32 @@ ImagingNewBlock(const char *mode, int xsize, int ysize) { Imaging im; Py_ssize_t y, i; - Py_ssize_t bytes; im = ImagingNewPrologue(mode, xsize, ysize); if (!im) return NULL; - /* Use a single block */ - bytes = (Py_ssize_t) im->ysize * im->linesize; - if (bytes <= 0) + /* We shouldn't overflow, since the threshold defined + below says that we're only going to allocate max 4M + here before going to the array allocator. Check anyway. + */ + if (im->linesize && + im->ysize > INT_MAX / im->linesize) { + /* punt if we're going to overflow */ + return NULL; + } + + if (im->ysize * im->linesize <= 0) { /* some platforms return NULL for malloc(0); this fix prevents MemoryError on zero-sized images on such platforms */ - bytes = 1; - im->block = (char *) malloc(bytes); + im->block = (char *) malloc(1); + } else { + /* malloc check ok, overflow check above */ + im->block = (char *) calloc(im->ysize, im->linesize); + } 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; @@ -392,7 +406,7 @@ ImagingNew(const char* mode, int xsize, int ysize) } else bytes = strlen(mode); /* close enough */ - if ((int64_t) xsize * (int64_t) ysize * bytes <= THRESHOLD) { + if ((int64_t) xsize * (int64_t) ysize <= THRESHOLD / bytes) { im = ImagingNewBlock(mode, xsize, ysize); if (im) return im; diff --git a/libImaging/TiffDecode.c b/libImaging/TiffDecode.c index b9b61e48f..8793f2b34 100644 --- a/libImaging/TiffDecode.c +++ b/libImaging/TiffDecode.c @@ -58,10 +58,14 @@ tsize_t _tiffWriteProc(thandle_t hdata, tdata_t buf, tsize_t size) { tdata_t new; tsize_t newsize=state->size; while (newsize < (size + state->size)) { + if (newsize > (tsize_t)SIZE_MAX - 64*1024){ + return 0; + } newsize += 64*1024; // newsize*=2; // UNDONE, by 64k chunks? } TRACE(("Reallocing in write to %d bytes\n", (int)newsize)); + /* malloc check ok, overflow checked above */ new = realloc(state->data, newsize); if (!new) { // fail out @@ -305,6 +309,7 @@ int ImagingLibTiffEncodeInit(ImagingCodecState state, char *filename, int fp) { } else { // malloc a buffer to write the tif, we're going to need to realloc or something if we need bigger. TRACE(("Opening a buffer for writing \n")); + /* malloc check ok, small constant allocation */ clientstate->data = malloc(bufsize); clientstate->size = bufsize; clientstate->flrealloc=1; diff --git a/libImaging/ZipDecode.c b/libImaging/ZipDecode.c index 707033a66..bbf011147 100644 --- a/libImaging/ZipDecode.c +++ b/libImaging/ZipDecode.c @@ -18,7 +18,7 @@ #include "Imaging.h" -#ifdef HAVE_LIBZ +#ifdef HAVE_LIBZ #include "Zip.h" @@ -37,7 +37,7 @@ static int get_row_len(ImagingCodecState state, int pass) } /* -------------------------------------------------------------------- */ -/* Decoder */ +/* Decoder */ /* -------------------------------------------------------------------- */ int @@ -52,50 +52,56 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) if (!state->state) { - /* Initialization */ - if (context->mode == ZIP_PNG || context->mode == ZIP_PNG_PALETTE) - context->prefix = 1; /* PNG */ + /* Initialization */ + if (context->mode == ZIP_PNG || context->mode == ZIP_PNG_PALETTE) + context->prefix = 1; /* PNG */ - /* Expand standard buffer to make room for the (optional) filter - prefix, and allocate a buffer to hold the previous line */ - free(state->buffer); - state->buffer = (UINT8*) malloc(state->bytes+1); - context->previous = (UINT8*) malloc(state->bytes+1); - if (!state->buffer || !context->previous) { - state->errcode = IMAGING_CODEC_MEMORY; - return -1; - } + /* overflow check for malloc */ + if (state->bytes > INT_MAX - 1) { + state->errcode = IMAGING_CODEC_MEMORY; + return -1; + } + /* Expand standard buffer to make room for the (optional) filter + prefix, and allocate a buffer to hold the previous line */ + free(state->buffer); + /* malloc check ok, overflow checked above */ + state->buffer = (UINT8*) malloc(state->bytes+1); + context->previous = (UINT8*) malloc(state->bytes+1); + if (!state->buffer || !context->previous) { + state->errcode = IMAGING_CODEC_MEMORY; + return -1; + } context->last_output = 0; - /* Initialize to black */ - memset(context->previous, 0, state->bytes+1); + /* Initialize to black */ + memset(context->previous, 0, state->bytes+1); - /* Setup decompression context */ - context->z_stream.zalloc = (alloc_func) NULL; - context->z_stream.zfree = (free_func) NULL; - context->z_stream.opaque = (voidpf) NULL; + /* Setup decompression context */ + context->z_stream.zalloc = (alloc_func) NULL; + context->z_stream.zfree = (free_func) NULL; + context->z_stream.opaque = (voidpf) NULL; - err = inflateInit(&context->z_stream); - if (err < 0) { - state->errcode = IMAGING_CODEC_CONFIG; - return -1; - } + err = inflateInit(&context->z_stream); + if (err < 0) { + state->errcode = IMAGING_CODEC_CONFIG; + return -1; + } - if (context->interlaced) { - context->pass = 0; - state->y = STARTING_ROW[context->pass]; - } + if (context->interlaced) { + context->pass = 0; + state->y = STARTING_ROW[context->pass]; + } - /* Ready to decode */ - state->state = 1; + /* Ready to decode */ + state->state = 1; } if (context->interlaced) { - row_len = get_row_len(state, context->pass); + row_len = get_row_len(state, context->pass); } else { - row_len = state->bytes; + row_len = state->bytes; } /* Setup the source buffer */ @@ -105,162 +111,162 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) /* Decompress what we've got this far */ while (context->z_stream.avail_in > 0) { - context->z_stream.next_out = state->buffer + context->last_output; - context->z_stream.avail_out = - row_len + context->prefix - context->last_output; + context->z_stream.next_out = state->buffer + context->last_output; + context->z_stream.avail_out = + row_len + context->prefix - context->last_output; - err = inflate(&context->z_stream, Z_NO_FLUSH); + err = inflate(&context->z_stream, Z_NO_FLUSH); - if (err < 0) { - /* Something went wrong inside the compression library */ - if (err == Z_DATA_ERROR) - state->errcode = IMAGING_CODEC_BROKEN; - else if (err == Z_MEM_ERROR) - state->errcode = IMAGING_CODEC_MEMORY; - else - state->errcode = IMAGING_CODEC_CONFIG; - free(context->previous); - inflateEnd(&context->z_stream); - return -1; - } + if (err < 0) { + /* Something went wrong inside the compression library */ + if (err == Z_DATA_ERROR) + state->errcode = IMAGING_CODEC_BROKEN; + else if (err == Z_MEM_ERROR) + state->errcode = IMAGING_CODEC_MEMORY; + else + state->errcode = IMAGING_CODEC_CONFIG; + free(context->previous); + inflateEnd(&context->z_stream); + return -1; + } - n = row_len + context->prefix - context->z_stream.avail_out; + n = row_len + context->prefix - context->z_stream.avail_out; - if (n < row_len + context->prefix) { - context->last_output = n; - break; /* need more input data */ - } + if (n < row_len + context->prefix) { + context->last_output = n; + break; /* need more input data */ + } - /* Apply predictor */ - switch (context->mode) { - case ZIP_PNG: - switch (state->buffer[0]) { - case 0: - break; - case 1: - /* prior */ - bpp = (state->bits + 7) / 8; - for (i = bpp+1; i <= row_len; i++) - state->buffer[i] += state->buffer[i-bpp]; - break; - case 2: - /* up */ - for (i = 1; i <= row_len; i++) - state->buffer[i] += context->previous[i]; - break; - case 3: - /* average */ - bpp = (state->bits + 7) / 8; - for (i = 1; i <= bpp; i++) - state->buffer[i] += context->previous[i]/2; - for (; i <= row_len; i++) - state->buffer[i] += - (state->buffer[i-bpp] + context->previous[i])/2; - break; - case 4: - /* paeth filtering */ - bpp = (state->bits + 7) / 8; - for (i = 1; i <= bpp; i++) - state->buffer[i] += context->previous[i]; - for (; i <= row_len; i++) { - int a, b, c; - int pa, pb, pc; + /* Apply predictor */ + switch (context->mode) { + case ZIP_PNG: + switch (state->buffer[0]) { + case 0: + break; + case 1: + /* prior */ + bpp = (state->bits + 7) / 8; + for (i = bpp+1; i <= row_len; i++) + state->buffer[i] += state->buffer[i-bpp]; + break; + case 2: + /* up */ + for (i = 1; i <= row_len; i++) + state->buffer[i] += context->previous[i]; + break; + case 3: + /* average */ + bpp = (state->bits + 7) / 8; + for (i = 1; i <= bpp; i++) + state->buffer[i] += context->previous[i]/2; + for (; i <= row_len; i++) + state->buffer[i] += + (state->buffer[i-bpp] + context->previous[i])/2; + break; + case 4: + /* paeth filtering */ + bpp = (state->bits + 7) / 8; + for (i = 1; i <= bpp; i++) + state->buffer[i] += context->previous[i]; + for (; i <= row_len; i++) { + int a, b, c; + int pa, pb, pc; - /* fetch pixels */ - a = state->buffer[i-bpp]; - b = context->previous[i]; - c = context->previous[i-bpp]; + /* fetch pixels */ + a = state->buffer[i-bpp]; + b = context->previous[i]; + c = context->previous[i-bpp]; - /* distances to surrounding pixels */ - pa = abs(b - c); - pb = abs(a - c); - pc = abs(a + b - 2*c); + /* distances to surrounding pixels */ + pa = abs(b - c); + pb = abs(a - c); + pc = abs(a + b - 2*c); - /* pick predictor with the shortest distance */ - state->buffer[i] += - (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c; + /* pick predictor with the shortest distance */ + state->buffer[i] += + (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c; - } - break; - default: - state->errcode = IMAGING_CODEC_UNKNOWN; - free(context->previous); - inflateEnd(&context->z_stream); - return -1; - } - break; - case ZIP_TIFF_PREDICTOR: - bpp = (state->bits + 7) / 8; - for (i = bpp+1; i <= row_len; i++) - state->buffer[i] += state->buffer[i-bpp]; - break; - } + } + break; + default: + state->errcode = IMAGING_CODEC_UNKNOWN; + free(context->previous); + inflateEnd(&context->z_stream); + return -1; + } + break; + case ZIP_TIFF_PREDICTOR: + bpp = (state->bits + 7) / 8; + for (i = bpp+1; i <= row_len; i++) + state->buffer[i] += state->buffer[i-bpp]; + break; + } - /* Stuff data into the image */ - if (context->interlaced) { - int col = STARTING_COL[context->pass]; - if (state->bits >= 8) { - /* Stuff pixels in their correct location, one by one */ - for (i = 0; i < row_len; i += ((state->bits + 7) / 8)) { - state->shuffle((UINT8*) im->image[state->y] + - col * im->pixelsize, - state->buffer + context->prefix + i, 1); - col += COL_INCREMENT[context->pass]; - } - } else { - /* Handle case with more than a pixel in each byte */ - int row_bits = ((state->xsize + OFFSET[context->pass]) - / COL_INCREMENT[context->pass]) * state->bits; - for (i = 0; i < row_bits; i += state->bits) { - UINT8 byte = *(state->buffer + context->prefix + (i / 8)); - byte <<= (i % 8); - state->shuffle((UINT8*) im->image[state->y] + - col * im->pixelsize, &byte, 1); - col += COL_INCREMENT[context->pass]; - } - } - /* Find next valid scanline */ - state->y += ROW_INCREMENT[context->pass]; - while (state->y >= state->ysize || row_len <= 0) { - context->pass++; - if (context->pass == 7) { - /* Force exit below */ - state->y = state->ysize; - break; - } - state->y = STARTING_ROW[context->pass]; - row_len = get_row_len(state, context->pass); - /* Since we're moving to the "first" line, the previous line - * should be black to make filters work corectly */ - memset(state->buffer, 0, state->bytes+1); - } - } else { - state->shuffle((UINT8*) im->image[state->y + state->yoff] + - state->xoff * im->pixelsize, - state->buffer + context->prefix, - state->xsize); - state->y++; - } + /* Stuff data into the image */ + if (context->interlaced) { + int col = STARTING_COL[context->pass]; + if (state->bits >= 8) { + /* Stuff pixels in their correct location, one by one */ + for (i = 0; i < row_len; i += ((state->bits + 7) / 8)) { + state->shuffle((UINT8*) im->image[state->y] + + col * im->pixelsize, + state->buffer + context->prefix + i, 1); + col += COL_INCREMENT[context->pass]; + } + } else { + /* Handle case with more than a pixel in each byte */ + int row_bits = ((state->xsize + OFFSET[context->pass]) + / COL_INCREMENT[context->pass]) * state->bits; + for (i = 0; i < row_bits; i += state->bits) { + UINT8 byte = *(state->buffer + context->prefix + (i / 8)); + byte <<= (i % 8); + state->shuffle((UINT8*) im->image[state->y] + + col * im->pixelsize, &byte, 1); + col += COL_INCREMENT[context->pass]; + } + } + /* Find next valid scanline */ + state->y += ROW_INCREMENT[context->pass]; + while (state->y >= state->ysize || row_len <= 0) { + context->pass++; + if (context->pass == 7) { + /* Force exit below */ + state->y = state->ysize; + break; + } + state->y = STARTING_ROW[context->pass]; + row_len = get_row_len(state, context->pass); + /* Since we're moving to the "first" line, the previous line + * should be black to make filters work corectly */ + memset(state->buffer, 0, state->bytes+1); + } + } else { + state->shuffle((UINT8*) im->image[state->y + state->yoff] + + state->xoff * im->pixelsize, + state->buffer + context->prefix, + state->xsize); + state->y++; + } /* all inflate output has been consumed */ context->last_output = 0; - if (state->y >= state->ysize || err == Z_STREAM_END) { + if (state->y >= state->ysize || err == Z_STREAM_END) { - /* The image and the data should end simultaneously */ - /* if (state->y < state->ysize || err != Z_STREAM_END) - state->errcode = IMAGING_CODEC_BROKEN; */ + /* The image and the data should end simultaneously */ + /* if (state->y < state->ysize || err != Z_STREAM_END) + state->errcode = IMAGING_CODEC_BROKEN; */ - free(context->previous); - inflateEnd(&context->z_stream); - return -1; /* end of file (errcode=0) */ + free(context->previous); + inflateEnd(&context->z_stream); + return -1; /* end of file (errcode=0) */ - } + } - /* Swap buffer pointers */ - ptr = state->buffer; - state->buffer = context->previous; - context->previous = ptr; + /* Swap buffer pointers */ + ptr = state->buffer; + state->buffer = context->previous; + context->previous = ptr; } diff --git a/libImaging/ZipEncode.c b/libImaging/ZipEncode.c index a4f76ffb4..d642e6da2 100644 --- a/libImaging/ZipEncode.c +++ b/libImaging/ZipEncode.c @@ -5,8 +5,8 @@ * coder for ZIP (deflated) image data * * History: - * 96-12-29 fl created - * 96-12-30 fl adaptive filter selection, encoder tuning + * 96-12-29 fl created + * 96-12-30 fl adaptive filter selection, encoder tuning * * Copyright (c) Fredrik Lundh 1996. * Copyright (c) Secret Labs AB 1997. @@ -17,7 +17,7 @@ #include "Imaging.h" -#ifdef HAVE_LIBZ +#ifdef HAVE_LIBZ #include "Zip.h" @@ -33,82 +33,89 @@ ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) if (!state->state) { - /* Initialization */ + /* Initialization */ - /* Valid modes are ZIP_PNG, ZIP_PNG_PALETTE, and ZIP_TIFF */ + /* Valid modes are ZIP_PNG, ZIP_PNG_PALETTE, and ZIP_TIFF */ - /* Expand standard buffer to make room for the filter selector, - and allocate filter buffers */ - free(state->buffer); - state->buffer = (UINT8*) malloc(state->bytes+1); - context->previous = (UINT8*) malloc(state->bytes+1); - context->prior = (UINT8*) malloc(state->bytes+1); - context->up = (UINT8*) malloc(state->bytes+1); - context->average = (UINT8*) malloc(state->bytes+1); - context->paeth = (UINT8*) malloc(state->bytes+1); - if (!state->buffer || !context->previous || !context->prior || - !context->up || !context->average || !context->paeth) { - free(context->paeth); - free(context->average); - free(context->up); - free(context->prior); - free(context->previous); - state->errcode = IMAGING_CODEC_MEMORY; - return -1; - } + /* overflow check for malloc */ + if (state->bytes > INT_MAX - 1) { + state->errcode = IMAGING_CODEC_MEMORY; + return -1; + } + + /* Expand standard buffer to make room for the filter selector, + and allocate filter buffers */ + free(state->buffer); + /* malloc check ok, overflow checked above */ + state->buffer = (UINT8*) malloc(state->bytes+1); + context->previous = (UINT8*) malloc(state->bytes+1); + context->prior = (UINT8*) malloc(state->bytes+1); + context->up = (UINT8*) malloc(state->bytes+1); + context->average = (UINT8*) malloc(state->bytes+1); + context->paeth = (UINT8*) malloc(state->bytes+1); + if (!state->buffer || !context->previous || !context->prior || + !context->up || !context->average || !context->paeth) { + free(context->paeth); + free(context->average); + free(context->up); + free(context->prior); + free(context->previous); + state->errcode = IMAGING_CODEC_MEMORY; + return -1; + } - /* Initalise filter buffers */ - state->buffer[0] = 0; - context->prior[0] = 1; - context->up[0] = 2; - context->average[0] = 3; - context->paeth[0] = 4; + /* Initalise filter buffers */ + state->buffer[0] = 0; + context->prior[0] = 1; + context->up[0] = 2; + context->average[0] = 3; + context->paeth[0] = 4; - /* Initialise previous buffer to black */ - memset(context->previous, 0, state->bytes+1); + /* Initialise previous buffer to black */ + memset(context->previous, 0, state->bytes+1); - /* Setup compression context */ - context->z_stream.zalloc = (alloc_func)0; - context->z_stream.zfree = (free_func)0; - context->z_stream.opaque = (voidpf)0; - context->z_stream.next_in = 0; - context->z_stream.avail_in = 0; + /* Setup compression context */ + context->z_stream.zalloc = (alloc_func)0; + context->z_stream.zfree = (free_func)0; + context->z_stream.opaque = (voidpf)0; + context->z_stream.next_in = 0; + context->z_stream.avail_in = 0; - compress_level = (context->optimize) ? Z_BEST_COMPRESSION - : context->compress_level; + compress_level = (context->optimize) ? Z_BEST_COMPRESSION + : context->compress_level; - if (context->compress_type == -1) { - compress_type = (context->mode == ZIP_PNG) ? Z_FILTERED - : Z_DEFAULT_STRATEGY; - } else { - compress_type = context->compress_type; - } + if (context->compress_type == -1) { + compress_type = (context->mode == ZIP_PNG) ? Z_FILTERED + : Z_DEFAULT_STRATEGY; + } else { + compress_type = context->compress_type; + } - err = deflateInit2(&context->z_stream, - /* compression level */ - compress_level, - /* compression method */ - Z_DEFLATED, - /* compression memory resources */ - 15, 9, - /* compression strategy (image data are filtered)*/ - compress_type); - if (err < 0) { - state->errcode = IMAGING_CODEC_CONFIG; - return -1; - } + err = deflateInit2(&context->z_stream, + /* compression level */ + compress_level, + /* compression method */ + Z_DEFLATED, + /* compression memory resources */ + 15, 9, + /* compression strategy (image data are filtered)*/ + compress_type); + if (err < 0) { + state->errcode = IMAGING_CODEC_CONFIG; + return -1; + } - if (context->dictionary && context->dictionary_size > 0) { - err = deflateSetDictionary(&context->z_stream, (unsigned char *)context->dictionary, - context->dictionary_size); - if (err < 0) { - state->errcode = IMAGING_CODEC_CONFIG; - return -1; - } - } + if (context->dictionary && context->dictionary_size > 0) { + err = deflateSetDictionary(&context->z_stream, (unsigned char *)context->dictionary, + context->dictionary_size); + if (err < 0) { + state->errcode = IMAGING_CODEC_CONFIG; + return -1; + } + } - /* Ready to decode */ - state->state = 1; + /* Ready to decode */ + state->state = 1; } @@ -116,222 +123,222 @@ ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) context->z_stream.next_out = buf; context->z_stream.avail_out = bytes; if (context->z_stream.next_in && context->z_stream.avail_in > 0) { - /* We have some data from previous round, deflate it first */ - err = deflate(&context->z_stream, Z_NO_FLUSH); + /* We have some data from previous round, deflate it first */ + err = deflate(&context->z_stream, Z_NO_FLUSH); - if (err < 0) { - /* Something went wrong inside the compression library */ - if (err == Z_DATA_ERROR) - state->errcode = IMAGING_CODEC_BROKEN; - else if (err == Z_MEM_ERROR) - state->errcode = IMAGING_CODEC_MEMORY; - else - state->errcode = IMAGING_CODEC_CONFIG; - free(context->paeth); - free(context->average); - free(context->up); - free(context->prior); - free(context->previous); - deflateEnd(&context->z_stream); - return -1; - } + if (err < 0) { + /* Something went wrong inside the compression library */ + if (err == Z_DATA_ERROR) + state->errcode = IMAGING_CODEC_BROKEN; + else if (err == Z_MEM_ERROR) + state->errcode = IMAGING_CODEC_MEMORY; + else + state->errcode = IMAGING_CODEC_CONFIG; + free(context->paeth); + free(context->average); + free(context->up); + free(context->prior); + free(context->previous); + deflateEnd(&context->z_stream); + return -1; + } } ImagingSectionEnter(&cookie); for (;;) { - switch (state->state) { + switch (state->state) { - case 1: + case 1: - /* Compress image data */ - while (context->z_stream.avail_out > 0) { + /* Compress image data */ + while (context->z_stream.avail_out > 0) { - if (state->y >= state->ysize) { - /* End of image; now flush compressor buffers */ - state->state = 2; - break; + if (state->y >= state->ysize) { + /* End of image; now flush compressor buffers */ + state->state = 2; + break; - } + } - /* Stuff image data into the compressor */ - state->shuffle(state->buffer+1, - (UINT8*) im->image[state->y + state->yoff] + - state->xoff * im->pixelsize, - state->xsize); + /* Stuff image data into the compressor */ + state->shuffle(state->buffer+1, + (UINT8*) im->image[state->y + state->yoff] + + state->xoff * im->pixelsize, + state->xsize); - state->y++; + state->y++; - context->output = state->buffer; + context->output = state->buffer; - if (context->mode == ZIP_PNG) { + if (context->mode == ZIP_PNG) { - /* Filter the image data. For each line, select - the filter that gives the least total distance - from zero for the filtered data (taken from - LIBPNG) */ + /* Filter the image data. For each line, select + the filter that gives the least total distance + from zero for the filtered data (taken from + LIBPNG) */ - bpp = (state->bits + 7) / 8; + bpp = (state->bits + 7) / 8; - /* 0. No filter */ - for (i = 1, sum = 0; i <= state->bytes; i++) { - UINT8 v = state->buffer[i]; - sum += (v < 128) ? v : 256 - v; - } + /* 0. No filter */ + for (i = 1, sum = 0; i <= state->bytes; i++) { + UINT8 v = state->buffer[i]; + sum += (v < 128) ? v : 256 - v; + } - /* 2. Up. We'll test this first to save time when - an image line is identical to the one above. */ - if (sum > 0) { - for (i = 1, s = 0; i <= state->bytes; i++) { - UINT8 v = state->buffer[i] - context->previous[i]; - context->up[i] = v; - s += (v < 128) ? v : 256 - v; - } - if (s < sum) { - context->output = context->up; - sum = s; /* 0 if line was duplicated */ - } - } + /* 2. Up. We'll test this first to save time when + an image line is identical to the one above. */ + if (sum > 0) { + for (i = 1, s = 0; i <= state->bytes; i++) { + UINT8 v = state->buffer[i] - context->previous[i]; + context->up[i] = v; + s += (v < 128) ? v : 256 - v; + } + if (s < sum) { + context->output = context->up; + sum = s; /* 0 if line was duplicated */ + } + } - /* 1. Prior */ - if (sum > 0) { - for (i = 1, s = 0; i <= bpp; i++) { - UINT8 v = state->buffer[i]; - context->prior[i] = v; - s += (v < 128) ? v : 256 - v; - } - for (; i <= state->bytes; i++) { - UINT8 v = state->buffer[i] - state->buffer[i-bpp]; - context->prior[i] = v; - s += (v < 128) ? v : 256 - v; - } - if (s < sum) { - context->output = context->prior; - sum = s; /* 0 if line is solid */ - } - } + /* 1. Prior */ + if (sum > 0) { + for (i = 1, s = 0; i <= bpp; i++) { + UINT8 v = state->buffer[i]; + context->prior[i] = v; + s += (v < 128) ? v : 256 - v; + } + for (; i <= state->bytes; i++) { + UINT8 v = state->buffer[i] - state->buffer[i-bpp]; + context->prior[i] = v; + s += (v < 128) ? v : 256 - v; + } + if (s < sum) { + context->output = context->prior; + sum = s; /* 0 if line is solid */ + } + } - /* 3. Average (not very common in real-life images, - so its only used with the optimize option) */ - if (context->optimize && sum > 0) { - for (i = 1, s = 0; i <= bpp; i++) { - UINT8 v = state->buffer[i] - context->previous[i]/2; - context->average[i] = v; - s += (v < 128) ? v : 256 - v; - } - for (; i <= state->bytes; i++) { - UINT8 v = state->buffer[i] - - (state->buffer[i-bpp] + context->previous[i])/2; - context->average[i] = v; - s += (v < 128) ? v : 256 - v; - } - if (s < sum) { - context->output = context->average; - sum = s; - } - } + /* 3. Average (not very common in real-life images, + so its only used with the optimize option) */ + if (context->optimize && sum > 0) { + for (i = 1, s = 0; i <= bpp; i++) { + UINT8 v = state->buffer[i] - context->previous[i]/2; + context->average[i] = v; + s += (v < 128) ? v : 256 - v; + } + for (; i <= state->bytes; i++) { + UINT8 v = state->buffer[i] - + (state->buffer[i-bpp] + context->previous[i])/2; + context->average[i] = v; + s += (v < 128) ? v : 256 - v; + } + if (s < sum) { + context->output = context->average; + sum = s; + } + } - /* 4. Paeth */ - if (sum > 0) { - for (i = 1, s = 0; i <= bpp; i++) { - UINT8 v = state->buffer[i] - context->previous[i]; - context->paeth[i] = v; - s += (v < 128) ? v : 256 - v; - } - for (; i <= state->bytes; i++) { - UINT8 v; - int a, b, c; - int pa, pb, pc; + /* 4. Paeth */ + if (sum > 0) { + for (i = 1, s = 0; i <= bpp; i++) { + UINT8 v = state->buffer[i] - context->previous[i]; + context->paeth[i] = v; + s += (v < 128) ? v : 256 - v; + } + for (; i <= state->bytes; i++) { + UINT8 v; + int a, b, c; + int pa, pb, pc; - /* fetch pixels */ - a = state->buffer[i-bpp]; - b = context->previous[i]; - c = context->previous[i-bpp]; + /* fetch pixels */ + a = state->buffer[i-bpp]; + b = context->previous[i]; + c = context->previous[i-bpp]; - /* distances to surrounding pixels */ - pa = abs(b - c); - pb = abs(a - c); - pc = abs(a + b - 2*c); + /* distances to surrounding pixels */ + pa = abs(b - c); + pb = abs(a - c); + pc = abs(a + b - 2*c); - /* pick predictor with the shortest distance */ - v = state->buffer[i] - - ((pa <= pb && pa <= pc) ? a : + /* pick predictor with the shortest distance */ + v = state->buffer[i] - + ((pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c); - context->paeth[i] = v; - s += (v < 128) ? v : 256 - v; - } - if (s < sum) { - context->output = context->paeth; - sum = s; - } - } - } + context->paeth[i] = v; + s += (v < 128) ? v : 256 - v; + } + if (s < sum) { + context->output = context->paeth; + sum = s; + } + } + } - /* Compress this line */ - context->z_stream.next_in = context->output; - context->z_stream.avail_in = state->bytes+1; + /* Compress this line */ + context->z_stream.next_in = context->output; + context->z_stream.avail_in = state->bytes+1; - err = deflate(&context->z_stream, Z_NO_FLUSH); + err = deflate(&context->z_stream, Z_NO_FLUSH); - if (err < 0) { - /* Something went wrong inside the compression library */ - if (err == Z_DATA_ERROR) - state->errcode = IMAGING_CODEC_BROKEN; - else if (err == Z_MEM_ERROR) - state->errcode = IMAGING_CODEC_MEMORY; - else - state->errcode = IMAGING_CODEC_CONFIG; - free(context->paeth); - free(context->average); - free(context->up); - free(context->prior); - free(context->previous); - deflateEnd(&context->z_stream); - ImagingSectionLeave(&cookie); - return -1; - } + if (err < 0) { + /* Something went wrong inside the compression library */ + if (err == Z_DATA_ERROR) + state->errcode = IMAGING_CODEC_BROKEN; + else if (err == Z_MEM_ERROR) + state->errcode = IMAGING_CODEC_MEMORY; + else + state->errcode = IMAGING_CODEC_CONFIG; + free(context->paeth); + free(context->average); + free(context->up); + free(context->prior); + free(context->previous); + deflateEnd(&context->z_stream); + ImagingSectionLeave(&cookie); + return -1; + } - /* Swap buffer pointers */ - ptr = state->buffer; - state->buffer = context->previous; - context->previous = ptr; + /* Swap buffer pointers */ + ptr = state->buffer; + state->buffer = context->previous; + context->previous = ptr; - } + } - if (context->z_stream.avail_out == 0) - break; /* Buffer full */ + if (context->z_stream.avail_out == 0) + break; /* Buffer full */ - case 2: + case 2: - /* End of image data; flush compressor buffers */ + /* End of image data; flush compressor buffers */ - while (context->z_stream.avail_out > 0) { + while (context->z_stream.avail_out > 0) { - err = deflate(&context->z_stream, Z_FINISH); + err = deflate(&context->z_stream, Z_FINISH); - if (err == Z_STREAM_END) { + if (err == Z_STREAM_END) { - free(context->paeth); - free(context->average); - free(context->up); - free(context->prior); - free(context->previous); + free(context->paeth); + free(context->average); + free(context->up); + free(context->prior); + free(context->previous); - deflateEnd(&context->z_stream); + deflateEnd(&context->z_stream); - state->errcode = IMAGING_CODEC_END; + state->errcode = IMAGING_CODEC_END; - break; - } + break; + } - if (context->z_stream.avail_out == 0) - break; /* Buffer full */ + if (context->z_stream.avail_out == 0) + break; /* Buffer full */ - } + } - } - ImagingSectionLeave(&cookie); - return bytes - context->z_stream.avail_out; + } + ImagingSectionLeave(&cookie); + return bytes - context->z_stream.avail_out; } @@ -341,6 +348,24 @@ ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) return -1; } +/* -------------------------------------------------------------------- */ +/* Cleanup */ +/* -------------------------------------------------------------------- */ + +int +ImagingZipEncodeCleanup(ImagingCodecState state) { + ZIPSTATE* context = (ZIPSTATE*) state->context; + + if (context->dictionary) { + free (context->dictionary); + context->dictionary = NULL; + } + + return -1; +} + + + const char* ImagingZipVersion(void) { diff --git a/path.c b/path.c index dd0ca8b4e..824fbdd89 100644 --- a/path.c +++ b/path.c @@ -37,7 +37,7 @@ extern int PyImaging_CheckBuffer(PyObject* buffer); extern int PyImaging_GetBuffer(PyObject* buffer, Py_buffer *view); /* -------------------------------------------------------------------- */ -/* Class */ +/* Class */ /* -------------------------------------------------------------------- */ typedef struct { @@ -86,7 +86,7 @@ path_new(Py_ssize_t count, double* xy, int duplicate) path = PyObject_New(PyPathObject, &PyPathType); if (path == NULL) - return NULL; + return NULL; path->count = count; path->xy = xy; @@ -102,26 +102,26 @@ path_dealloc(PyPathObject* path) } /* -------------------------------------------------------------------- */ -/* Helpers */ +/* Helpers */ /* -------------------------------------------------------------------- */ #define PyPath_Check(op) (Py_TYPE(op) == &PyPathType) -int +Py_ssize_t PyPath_Flatten(PyObject* data, double **pxy) { - int i, j, n; + Py_ssize_t i, j, n; double *xy; if (PyPath_Check(data)) { - /* This was another path object. */ - PyPathObject *path = (PyPathObject*) data; + /* This was another path object. */ + PyPathObject *path = (PyPathObject*) data; xy = alloc_array(path->count); - if (!xy) - return -1; - memcpy(xy, path->xy, 2 * path->count * sizeof(double)); - *pxy = xy; - return path->count; + if (!xy) + return -1; + memcpy(xy, path->xy, 2 * path->count * sizeof(double)); + *pxy = xy; + return path->count; } if (PyImaging_CheckBuffer(data)) { @@ -143,8 +143,8 @@ PyPath_Flatten(PyObject* data, double **pxy) } if (!PySequence_Check(data)) { - PyErr_SetString(PyExc_TypeError, "argument must be sequence"); - return -1; + PyErr_SetString(PyExc_TypeError, "argument must be sequence"); + return -1; } j = 0; @@ -156,7 +156,7 @@ PyPath_Flatten(PyObject* data, double **pxy) /* Allocate for worst case */ xy = alloc_array(n); if (!xy) - return -1; + return -1; /* Copy table to path array */ if (PyList_Check(data)) { @@ -164,9 +164,9 @@ PyPath_Flatten(PyObject* data, double **pxy) double x, y; PyObject *op = PyList_GET_ITEM(data, i); if (PyFloat_Check(op)) - xy[j++] = PyFloat_AS_DOUBLE(op); + xy[j++] = PyFloat_AS_DOUBLE(op); else if (PyInt_Check(op)) - xy[j++] = (float) PyInt_AS_LONG(op); + xy[j++] = (float) PyInt_AS_LONG(op); else if (PyNumber_Check(op)) xy[j++] = PyFloat_AsDouble(op); else if (PyArg_ParseTuple(op, "dd", &x, &y)) { @@ -182,9 +182,9 @@ PyPath_Flatten(PyObject* data, double **pxy) double x, y; PyObject *op = PyTuple_GET_ITEM(data, i); if (PyFloat_Check(op)) - xy[j++] = PyFloat_AS_DOUBLE(op); + xy[j++] = PyFloat_AS_DOUBLE(op); else if (PyInt_Check(op)) - xy[j++] = (float) PyInt_AS_LONG(op); + xy[j++] = (float) PyInt_AS_LONG(op); else if (PyNumber_Check(op)) xy[j++] = PyFloat_AsDouble(op); else if (PyArg_ParseTuple(op, "dd", &x, &y)) { @@ -211,9 +211,9 @@ PyPath_Flatten(PyObject* data, double **pxy) } } if (PyFloat_Check(op)) - xy[j++] = PyFloat_AS_DOUBLE(op); + xy[j++] = PyFloat_AS_DOUBLE(op); else if (PyInt_Check(op)) - xy[j++] = (float) PyInt_AS_LONG(op); + xy[j++] = (float) PyInt_AS_LONG(op); else if (PyNumber_Check(op)) xy[j++] = PyFloat_AsDouble(op); else if (PyArg_ParseTuple(op, "dd", &x, &y)) { @@ -229,9 +229,9 @@ PyPath_Flatten(PyObject* data, double **pxy) } if (j & 1) { - PyErr_SetString(PyExc_ValueError, "wrong number of coordinates"); - free(xy); - return -1; + PyErr_SetString(PyExc_ValueError, "wrong number of coordinates"); + free(xy); + return -1; } *pxy = xy; @@ -240,7 +240,7 @@ PyPath_Flatten(PyObject* data, double **pxy) /* -------------------------------------------------------------------- */ -/* Factories */ +/* Factories */ /* -------------------------------------------------------------------- */ PyObject* @@ -274,7 +274,7 @@ PyPath_Create(PyObject* self, PyObject* args) /* -------------------------------------------------------------------- */ -/* Methods */ +/* Methods */ /* -------------------------------------------------------------------- */ static PyObject* @@ -283,29 +283,30 @@ path_compact(PyPathObject* self, PyObject* args) /* Simple-minded method to shorten path. A point is removed if the city block distance to the previous point is less than the given distance */ - int i, j; + Py_ssize_t i, j; double *xy; double cityblock = 2.0; if (!PyArg_ParseTuple(args, "|d:compact", &cityblock)) - return NULL; + return NULL; xy = self->xy; /* remove bogus vertices */ for (i = j = 1; i < self->count; i++) { - if (fabs(xy[j+j-2]-xy[i+i]) + fabs(xy[j+j-1]-xy[i+i+1]) >= cityblock) { - xy[j+j] = xy[i+i]; - xy[j+j+1] = xy[i+i+1]; - j++; - } + if (fabs(xy[j+j-2]-xy[i+i]) + fabs(xy[j+j-1]-xy[i+i+1]) >= cityblock) { + xy[j+j] = xy[i+i]; + xy[j+j+1] = xy[i+i+1]; + j++; + } } i = self->count - j; self->count = j; /* shrink coordinate array */ + /* malloc check ok, self->count is smaller than it was before */ self->xy = realloc(self->xy, 2 * self->count * sizeof(double)); return Py_BuildValue("i", i); /* number of removed vertices */ @@ -331,12 +332,12 @@ static PyObject* path_getbbox(PyPathObject* self, PyObject* args) { /* Find bounding box */ - int i; + Py_ssize_t i; double *xy; double x0, y0, x1, y1; if (!PyArg_ParseTuple(args, ":getbbox")) - return NULL; + return NULL; xy = self->xy; @@ -344,27 +345,27 @@ path_getbbox(PyPathObject* self, PyObject* args) y0 = y1 = xy[1]; for (i = 1; i < self->count; i++) { - if (xy[i+i] < x0) - x0 = xy[i+i]; - if (xy[i+i] > x1) - x1 = xy[i+i]; - if (xy[i+i+1] < y0) - y0 = xy[i+i+1]; - if (xy[i+i+1] > y1) - y1 = xy[i+i+1]; + if (xy[i+i] < x0) + x0 = xy[i+i]; + if (xy[i+i] > x1) + x1 = xy[i+i]; + if (xy[i+i+1] < y0) + y0 = xy[i+i+1]; + if (xy[i+i+1] > y1) + y1 = xy[i+i+1]; } return Py_BuildValue("dddd", x0, y0, x1, y1); } static PyObject* -path_getitem(PyPathObject* self, int i) +path_getitem(PyPathObject* self, Py_ssize_t i) { if (i < 0) i = self->count + i; if (i < 0 || i >= self->count) { - PyErr_SetString(PyExc_IndexError, "path index out of range"); - return NULL; + PyErr_SetString(PyExc_IndexError, "path index out of range"); + return NULL; } return Py_BuildValue("dd", self->xy[i+i], self->xy[i+i+1]); @@ -398,27 +399,27 @@ static PyObject* path_map(PyPathObject* self, PyObject* args) { /* Map coordinate set through function */ - int i; + Py_ssize_t i; double *xy; PyObject* function; if (!PyArg_ParseTuple(args, "O:map", &function)) - return NULL; + return NULL; xy = self->xy; /* apply function to coordinate set */ for (i = 0; i < self->count; i++) { - double x = xy[i+i]; - double y = xy[i+i+1]; - PyObject* item = PyObject_CallFunction(function, "dd", x, y); - if (!item || !PyArg_ParseTuple(item, "dd", &x, &y)) { - Py_XDECREF(item); - return NULL; - } - xy[i+i] = x; - xy[i+i+1] = y; - Py_DECREF(item); + double x = xy[i+i]; + double y = xy[i+i+1]; + PyObject* item = PyObject_CallFunction(function, "dd", x, y); + if (!item || !PyArg_ParseTuple(item, "dd", &x, &y)) { + Py_XDECREF(item); + return NULL; + } + xy[i+i] = x; + xy[i+i+1] = y; + Py_DECREF(item); } Py_INCREF(Py_None); @@ -426,7 +427,7 @@ path_map(PyPathObject* self, PyObject* args) } static int -path_setitem(PyPathObject* self, int i, PyObject* op) +path_setitem(PyPathObject* self, Py_ssize_t i, PyObject* op) { double* xy; @@ -454,11 +455,11 @@ static PyObject* path_tolist(PyPathObject* self, PyObject* args) { PyObject *list; - int i; + Py_ssize_t i; int flat = 0; if (!PyArg_ParseTuple(args, "|i:tolist", &flat)) - return NULL; + return NULL; if (flat) { list = PyList_New(self->count*2); @@ -491,39 +492,39 @@ static PyObject* path_transform(PyPathObject* self, PyObject* args) { /* Apply affine transform to coordinate set */ - int i; + Py_ssize_t i; double *xy; double a, b, c, d, e, f; double wrap = 0.0; if (!PyArg_ParseTuple(args, "(dddddd)|d:transform", - &a, &b, &c, &d, &e, &f, - &wrap)) - return NULL; + &a, &b, &c, &d, &e, &f, + &wrap)) + return NULL; xy = self->xy; /* transform the coordinate set */ if (b == 0.0 && d == 0.0) - /* scaling */ - for (i = 0; i < self->count; i++) { - xy[i+i] = a*xy[i+i]+c; - xy[i+i+1] = e*xy[i+i+1]+f; - } + /* scaling */ + for (i = 0; i < self->count; i++) { + xy[i+i] = a*xy[i+i]+c; + xy[i+i+1] = e*xy[i+i+1]+f; + } else - /* affine transform */ - for (i = 0; i < self->count; i++) { - double x = xy[i+i]; - double y = xy[i+i+1]; - xy[i+i] = a*x+b*y+c; - xy[i+i+1] = d*x+e*y+f; - } + /* affine transform */ + for (i = 0; i < self->count; i++) { + double x = xy[i+i]; + double y = xy[i+i+1]; + xy[i+i] = a*x+b*y+c; + xy[i+i+1] = d*x+e*y+f; + } /* special treatment of geographical map data */ if (wrap != 0.0) - for (i = 0; i < self->count; i++) - xy[i+i] = fmod(xy[i+i], wrap); + for (i = 0; i < self->count; i++) + xy[i+i] = fmod(xy[i+i], wrap); Py_INCREF(Py_None); return Py_None; @@ -543,7 +544,7 @@ static struct PyMethodDef methods[] = { static PyObject* path_getattr_id(PyPathObject* self, void* closure) { - return Py_BuildValue("n", (Py_ssize_t) self->xy); + return Py_BuildValue("n", (Py_ssize_t) self->xy); } static struct PyGetSetDef getsetters[] = { @@ -593,13 +594,13 @@ path_subscript(PyPathObject* self, PyObject* item) { } static PySequenceMethods path_as_sequence = { - (lenfunc)path_len, /*sq_length*/ - (binaryfunc)0, /*sq_concat*/ - (ssizeargfunc)0, /*sq_repeat*/ - (ssizeargfunc)path_getitem, /*sq_item*/ - (ssizessizeargfunc)path_getslice, /*sq_slice*/ - (ssizeobjargproc)path_setitem, /*sq_ass_item*/ - (ssizessizeobjargproc)0, /*sq_ass_slice*/ + (lenfunc)path_len, /*sq_length*/ + (binaryfunc)0, /*sq_concat*/ + (ssizeargfunc)0, /*sq_repeat*/ + (ssizeargfunc)path_getitem, /*sq_item*/ + (ssizessizeargfunc)path_getslice, /*sq_slice*/ + (ssizeobjargproc)path_setitem, /*sq_ass_item*/ + (ssizessizeobjargproc)0, /*sq_ass_slice*/ }; static PyMappingMethods path_as_mapping = { @@ -609,19 +610,19 @@ static PyMappingMethods path_as_mapping = { }; static PyTypeObject PyPathType = { - PyVarObject_HEAD_INIT(NULL, 0) - "Path", /*tp_name*/ - sizeof(PyPathObject), /*tp_size*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)path_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number */ - &path_as_sequence, /*tp_as_sequence */ + PyVarObject_HEAD_INIT(NULL, 0) + "Path", /*tp_name*/ + sizeof(PyPathObject), /*tp_size*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor)path_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number */ + &path_as_sequence, /*tp_as_sequence */ &path_as_mapping, /*tp_as_mapping */ 0, /*tp_hash*/ 0, /*tp_call*/