diff --git a/CVE-2020-10177.patch b/CVE-2020-10177.patch new file mode 100644 index 0000000000000000000000000000000000000000..5b9dba991b913ad12450e4f99a7f5c4622136ffd --- /dev/null +++ b/CVE-2020-10177.patch @@ -0,0 +1,145 @@ +diff --git a/src/libImaging/FliDecode.c b/src/libImaging/FliDecode.c +index 600528e..2d63bea 100644 +--- a/src/libImaging/FliDecode.c ++++ b/src/libImaging/FliDecode.c +@@ -24,6 +24,11 @@ + #define I32(ptr)\ + ((ptr)[0] + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24)) + ++#define ERR_IF_DATA_OOB(offset) \ ++ if ((data + (offset)) > ptr + bytes) {\ ++ state->errcode = IMAGING_CODEC_OVERRUN; \ ++ return -1; \ ++ } + + int + ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) +@@ -75,10 +80,12 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) + break; /* ignored; handled by Python code */ + case 7: + /* FLI SS2 chunk (word delta) */ ++ /* OOB ok, we've got 4 bytes min on entry */ + lines = I16(data); data += 2; + for (l = y = 0; l < lines && y < state->ysize; l++, y++) { +- UINT8* buf = (UINT8*) im->image[y]; ++ UINT8* local_buf = (UINT8*) im->image[y]; + int p, packets; ++ ERR_IF_DATA_OOB(2) + packets = I16(data); data += 2; + while (packets & 0x8000) { + /* flag word */ +@@ -88,29 +95,33 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) + state->errcode = IMAGING_CODEC_OVERRUN; + return -1; + } +- buf = (UINT8*) im->image[y]; ++ local_buf = (UINT8*) im->image[y]; + } else { + /* store last byte (used if line width is odd) */ +- buf[state->xsize-1] = (UINT8) packets; ++ local_buf[state->xsize-1] = (UINT8) packets; + } ++ ERR_IF_DATA_OOB(2) + packets = I16(data); data += 2; + } + for (p = x = 0; p < packets; p++) { ++ ERR_IF_DATA_OOB(2) + x += data[0]; /* pixel skip */ + if (data[1] >= 128) { ++ ERR_IF_DATA_OOB(4) + i = 256-data[1]; /* run */ + if (x + i + i > state->xsize) + break; + for (j = 0; j < i; j++) { +- buf[x++] = data[2]; +- buf[x++] = data[3]; ++ local_buf[x++] = data[2]; ++ local_buf[x++] = data[3]; + } + data += 2 + 2; + } else { + i = 2 * (int) data[1]; /* chunk */ + if (x + i > state->xsize) + break; +- memcpy(buf + x, data + 2, i); ++ ERR_IF_DATA_OOB(2+i) ++ memcpy(local_buf + x, data + 2, i); + data += 2 + i; + x += i; + } +@@ -126,22 +137,26 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) + break; + case 12: + /* FLI LC chunk (byte delta) */ ++ /* OOB Check ok, we have 10 bytes here */ + y = I16(data); ymax = y + I16(data+2); data += 4; + for (; y < ymax && y < state->ysize; y++) { + UINT8* out = (UINT8*) im->image[y]; + int p, packets = *data++; + for (p = x = 0; p < packets; p++, x += i) { ++ ERR_IF_DATA_OOB(2) + x += data[0]; /* skip pixels */ + if (data[1] & 0x80) { + i = 256-data[1]; /* run */ + if (x + i > state->xsize) + break; ++ ERR_IF_DATA_OOB(3) + memset(out + x, data[2], i); + data += 3; + } else { + i = data[1]; /* chunk */ + if (x + i > state->xsize) + break; ++ ERR_IF_DATA_OOB(2+i) + memcpy(out + x, data + 2, i); + data += i + 2; + } +@@ -162,14 +177,20 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) + break; + case 15: + /* FLI BRUN chunk */ ++ /* data = ptr + 6 */ + for (y = 0; y < state->ysize; y++) { + UINT8* out = (UINT8*) im->image[y]; + data += 1; /* ignore packetcount byte */ + for (x = 0; x < state->xsize; x += i) { ++ /* Out of Bounds Read issue, guaranteed to try to read 2 from data */ ++ ERR_IF_DATA_OOB(2) + if (data[0] & 0x80) { + i = 256 - data[0]; +- if (x + i > state->xsize) ++ if (x + i > state->xsize){ + break; /* safety first */ ++ } ++ /* Out of Bounds read issue */ ++ ERR_IF_DATA_OOB(i+1) + memcpy(out + x, data + 1, i); + data += i + 1; + } else { +@@ -189,9 +210,13 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) + break; + case 16: + /* COPY chunk */ ++ if (state->xsize > bytes/state->ysize) { ++ /* not enough data for frame */ ++ return ptr - buf; /* bytes consumed */ ++ } + for (y = 0; y < state->ysize; y++) { +- UINT8* buf = (UINT8*) im->image[y]; +- memcpy(buf, data, state->xsize); ++ UINT8* local_buf = (UINT8*) im->image[y]; ++ memcpy(local_buf, data, state->xsize); + data += state->xsize; + } + break; +@@ -205,6 +230,10 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) + return -1; + } + advance = I32(ptr); ++ if (advance < 0 || advance > bytes) { ++ state->errcode = IMAGING_CODEC_OVERRUN; ++ return -1; ++ } + ptr += advance; + bytes -= advance; + } diff --git a/CVE-2020-10378.patch b/CVE-2020-10378.patch new file mode 100644 index 0000000000000000000000000000000000000000..2d41cc5ab2401c86cce3f1d688e4defd38bb7311 --- /dev/null +++ b/CVE-2020-10378.patch @@ -0,0 +1,22 @@ +From 6a83e4324738bb0452fbe8074a995b1c73f08de7 Mon Sep 17 00:00:00 2001 +From: Eric Soroos +Date: Mon, 9 Mar 2020 20:22:06 +0000 +Subject: [PATCH] Fix OOB Access on PcxDecode.c + +--- + src/libImaging/PcxDecode.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/src/libImaging/PcxDecode.c b/src/libImaging/PcxDecode.c +index 51de069..bf0eb00 100644 +--- a/src/libImaging/PcxDecode.c ++++ b/src/libImaging/PcxDecode.c +@@ -22,7 +22,7 @@ ImagingPcxDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) + UINT8 n; + UINT8* ptr; + +- if (strcmp(im->mode, "1") == 0 && state->xsize > state->bytes * 8) { ++ if ((state->xsize * state->bits + 7) / 8 > state->bytes) { + state->errcode = IMAGING_CODEC_OVERRUN; + return -1; + } diff --git a/CVE-2020-10994.patch b/CVE-2020-10994.patch new file mode 100644 index 0000000000000000000000000000000000000000..4874323f683f2c17e4f9708937c1c5fa724d9a76 --- /dev/null +++ b/CVE-2020-10994.patch @@ -0,0 +1,109 @@ +From cf6da6b79080a8c16984102fdc85f7ce28dca613 Mon Sep 17 00:00:00 2001 +From: Eric Soroos +Date: Mon, 9 Mar 2020 22:09:49 +0000 +Subject: [PATCH 1/4] Fix for OOB Read in DecodeJpeg2k + +--- + src/libImaging/Jpeg2KDecode.c | 60 +++++++++++++++++++++++++---------- + 1 file changed, 43 insertions(+), 17 deletions(-) + +diff --git a/src/libImaging/Jpeg2KDecode.c b/src/libImaging/Jpeg2KDecode.c +index 9140e00..8c231c1 100644 +--- a/src/libImaging/Jpeg2KDecode.c ++++ b/src/libImaging/Jpeg2KDecode.c +@@ -110,6 +110,7 @@ j2ku_gray_l(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, + if (shift < 0) + offset += 1 << (-shift - 1); + ++ /* csiz*h*w + offset = tileinfo.datasize */ + switch (csiz) { + case 1: + for (y = 0; y < h; ++y) { +@@ -557,8 +558,10 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) + opj_dparameters_t params; + OPJ_COLOR_SPACE color_space; + j2k_unpacker_t unpack = NULL; +- size_t buffer_size = 0; +- unsigned n; ++ size_t buffer_size = 0, tile_bytes = 0; ++ unsigned n, tile_height, tile_width; ++ int components; ++ + + stream = opj_stream_create(BUFFER_SIZE, OPJ_TRUE); + +@@ -703,8 +706,44 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) + tile_info.x1 = (tile_info.x1 + correction) >> context->reduce; + tile_info.y1 = (tile_info.y1 + correction) >> context->reduce; + ++ /* Check the tile bounds; if the tile is outside the image area, ++ or if it has a negative width or height (i.e. the coordinates are ++ swapped), bail. */ ++ if (tile_info.x0 >= tile_info.x1 ++ || tile_info.y0 >= tile_info.y1 ++ || tile_info.x0 < image->x0 ++ || tile_info.y0 < image->y0 ++ || tile_info.x1 - image->x0 > im->xsize ++ || tile_info.y1 - image->y0 > im->ysize) { ++ state->errcode = IMAGING_CODEC_BROKEN; ++ state->state = J2K_STATE_FAILED; ++ goto quick_exit; ++ } ++ ++ /* Sometimes the tile_info.datasize we get back from openjpeg ++ is less than numcomps*w*h, and we overflow in the ++ shuffle stage */ ++ ++ tile_width = tile_info.x1 - tile_info.x0; ++ tile_height = tile_info.y1 - tile_info.y0; ++ components = tile_info.nb_comps == 3 ? 4 : tile_info.nb_comps; ++ if (( tile_width > UINT_MAX / components ) || ++ ( tile_height > UINT_MAX / components ) || ++ ( tile_width > UINT_MAX / (tile_height * components )) || ++ ( tile_height > UINT_MAX / (tile_width * components ))) { ++ state->errcode = IMAGING_CODEC_BROKEN; ++ state->state = J2K_STATE_FAILED; ++ goto quick_exit; ++ } ++ ++ tile_bytes = tile_width * tile_height * components; ++ ++ if (tile_bytes > tile_info.data_size) { ++ tile_info.data_size = tile_bytes; ++ } ++ + if (buffer_size < tile_info.data_size) { +- /* malloc check ok, tile_info.data_size from openjpeg */ ++ /* malloc check ok, overflow and tile size sanity check above */ + UINT8 *new = realloc (state->buffer, tile_info.data_size); + if (!new) { + state->errcode = IMAGING_CODEC_MEMORY; +@@ -715,6 +754,7 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) + buffer_size = tile_info.data_size; + } + ++ + if (!opj_decode_tile_data(codec, + tile_info.tile_index, + (OPJ_BYTE *)state->buffer, +@@ -725,20 +765,6 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) + goto quick_exit; + } + +- /* Check the tile bounds; if the tile is outside the image area, +- or if it has a negative width or height (i.e. the coordinates are +- swapped), bail. */ +- if (tile_info.x0 >= tile_info.x1 +- || tile_info.y0 >= tile_info.y1 +- || tile_info.x0 < image->x0 +- || tile_info.y0 < image->y0 +- || tile_info.x1 - image->x0 > im->xsize +- || tile_info.y1 - image->y0 > im->ysize) { +- state->errcode = IMAGING_CODEC_BROKEN; +- state->state = J2K_STATE_FAILED; +- goto quick_exit; +- } +- + unpack(image, &tile_info, state->buffer, im); + } + diff --git a/CVE-2020-11538.patch b/CVE-2020-11538.patch new file mode 100644 index 0000000000000000000000000000000000000000..db2c68c9e440365c1f9ebec5e0ffbcb4c0ffd1f1 --- /dev/null +++ b/CVE-2020-11538.patch @@ -0,0 +1,55 @@ +From 394d6a180a4b63a149a223b13e98a3209f837147 Mon Sep 17 00:00:00 2001 +From: Eric Soroos +Date: Sat, 28 Mar 2020 13:00:46 +0000 +Subject: [PATCH 1/4] Track number of pixels, not the number of runs + +--- + src/libImaging/SgiRleDecode.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/src/libImaging/SgiRleDecode.c b/src/libImaging/SgiRleDecode.c +index e9b2c0b..087b7b4 100644 +--- a/src/libImaging/SgiRleDecode.c ++++ b/src/libImaging/SgiRleDecode.c +@@ -28,6 +28,7 @@ static void read4B(UINT32* dest, UINT8* buf) + static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize) + { + UINT8 pixel, count; ++ int x = 0; + + for (;n > 0; n--) + { +@@ -37,9 +38,10 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize) + count = pixel & RLE_MAX_RUN; + if (!count) + return count; +- if (count > xsize){ ++ if (x + count > xsize){ + return -1; + } ++ x += count; + if (pixel & RLE_COPY_FLAG) { + while(count--) { + *dest = *src++; +@@ -62,7 +64,8 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize) + static int expandrow2(UINT8* dest, const UINT8* src, int n, int z, int xsize) + { + UINT8 pixel, count; +- ++ ++ int x = 0; + + for (;n > 0; n--) + { +@@ -73,9 +76,10 @@ static int expandrow2(UINT8* dest, const UINT8* src, int n, int z, int xsize) + count = pixel & RLE_MAX_RUN; + if (!count) + return count; +- if (count > xsize){ ++ if (x + count > xsize){ + return -1; + } ++ x += count; + if (pixel & RLE_COPY_FLAG) { + while(count--) { + memcpy(dest, src, 2); diff --git a/pre-CVE-2020-11538-1.patch b/pre-CVE-2020-11538-1.patch new file mode 100644 index 0000000000000000000000000000000000000000..337ca4d00db38811a5cf89da3f3e55179367d25a --- /dev/null +++ b/pre-CVE-2020-11538-1.patch @@ -0,0 +1,1599 @@ +From 7a4af2b7671b14163f61c7f88889fad66e50d77b Mon Sep 17 00:00:00 2001 +From: Rolf Eike Beer +Date: Sun, 1 Jul 2018 12:47:59 +0200 +Subject: [PATCH] fix unaligned accesses by using memcpy() + +https://github.com/python-pillow/Pillow/commit/7a4af2b7671b14163f61c7f88889fad66e50d77b + +--- + src/_imaging.c | 31 +++-- + src/libImaging/Access.c | 16 +-- + src/libImaging/Bands.c | 30 +++-- + src/libImaging/ColorLUT.c | 10 +- + src/libImaging/Convert.c | 165 +++++++++++++++------------ + src/libImaging/Filter.c | 33 ++++-- + src/libImaging/Geometry.c | 18 ++- + src/libImaging/GetBBox.c | 24 ++-- + src/libImaging/Histo.c | 4 +- + src/libImaging/Pack.c | 13 ++- + src/libImaging/Point.c | 16 ++- + src/libImaging/Resample.c | 30 +++-- + src/libImaging/SgiRleDecode.c | 19 ++-- + src/libImaging/Unpack.c | 209 +++++++++++++++++----------------- + 14 files changed, 353 insertions(+), 265 deletions(-) + +diff --git a/src/_imaging.c b/src/_imaging.c +index e4b31f1..56fa0b6 100644 +--- a/src/_imaging.c ++++ b/src/_imaging.c +@@ -374,7 +374,8 @@ getlist(PyObject* arg, Py_ssize_t* length, const char* wrong_length, int type) + Py_ssize_t i, n; + int itemp; + double dtemp; +- void* list; ++ FLOAT32 ftemp; ++ UINT8* list; + PyObject* seq; + PyObject* op; + +@@ -408,19 +409,19 @@ getlist(PyObject* arg, Py_ssize_t* length, const char* wrong_length, int type) + switch (type) { + case TYPE_UINT8: + itemp = PyInt_AsLong(op); +- ((UINT8*)list)[i] = CLIP8(itemp); ++ list[i] = CLIP8(itemp); + break; + case TYPE_INT32: + itemp = PyInt_AsLong(op); +- ((INT32*)list)[i] = itemp; ++ memcpy(list + i * sizeof(INT32), &itemp, sizeof(itemp)); + break; + case TYPE_FLOAT32: +- dtemp = PyFloat_AsDouble(op); +- ((FLOAT32*)list)[i] = (FLOAT32) dtemp; ++ ftemp = (FLOAT32)PyFloat_AsDouble(op); ++ memcpy(list + i * sizeof(ftemp), &ftemp, sizeof(ftemp)); + break; + case TYPE_DOUBLE: + dtemp = PyFloat_AsDouble(op); +- ((double*)list)[i] = (double) dtemp; ++ memcpy(list + i * sizeof(dtemp), &dtemp, sizeof(dtemp)); + break; + } + } +@@ -517,6 +518,8 @@ getink(PyObject* color, Imaging im, char* ink) + to return it into a 32 bit C long + */ + PY_LONG_LONG r = 0; ++ FLOAT32 ftmp; ++ INT32 itmp; + + /* fill ink buffer (four bytes) with something that can + be cast to either UINT8 or INT32 */ +@@ -582,14 +585,16 @@ getink(PyObject* color, Imaging im, char* ink) + /* signed integer */ + if (rIsInt != 1) + return NULL; +- *(INT32*) ink = r; ++ itmp = r; ++ memcpy(ink, &itmp, sizeof(itmp)); + return ink; + case IMAGING_TYPE_FLOAT32: + /* floating point */ + f = PyFloat_AsDouble(color); + if (f == -1.0 && PyErr_Occurred()) + return NULL; +- *(FLOAT32*) ink = (FLOAT32) f; ++ ftmp = f; ++ memcpy(ink, &ftmp, sizeof(ftmp)); + return ink; + case IMAGING_TYPE_SPECIAL: + if (strncmp(im->mode, "I;16", 4) == 0) { +@@ -784,15 +789,19 @@ _prepare_lut_table(PyObject* table, Py_ssize_t table_size) + } + + for (i = 0; i < table_size; i++) { ++ FLOAT16 htmp; ++ double dtmp; + switch (data_type) { + case TYPE_FLOAT16: +- item = float16tofloat32(((FLOAT16*) table_data)[i]); ++ memcpy(&htmp, ((char*) table_data) + i * sizeof(htmp), sizeof(htmp)); ++ item = float16tofloat32(htmp); + break; + case TYPE_FLOAT32: +- item = ((FLOAT32*) table_data)[i]; ++ memcpy(&item, ((char*) table_data) + i * sizeof(FLOAT32), sizeof(FLOAT32)); + break; + case TYPE_DOUBLE: +- item = ((double*) table_data)[i]; ++ memcpy(&dtmp, ((char*) table_data) + i * sizeof(dtmp), sizeof(dtmp)); ++ item = (FLOAT32) dtmp; + break; + } + /* Max value for INT16 */ +diff --git a/src/libImaging/Access.c b/src/libImaging/Access.c +index 8d27a0a..15ffa11 100644 +--- a/src/libImaging/Access.c ++++ b/src/libImaging/Access.c +@@ -95,8 +95,8 @@ get_pixel_16L(Imaging im, int x, int y, void* color) + { + UINT8* in = (UINT8*) &im->image[y][x+x]; + #ifdef WORDS_BIGENDIAN +- UINT16* out = color; +- out[0] = in[0] + (in[1]<<8); ++ UINT16 out = in[0] + (in[1]<<8); ++ memcpy(color, &out, sizeof(out)); + #else + memcpy(color, in, sizeof(UINT16)); + #endif +@@ -109,8 +109,8 @@ get_pixel_16B(Imaging im, int x, int y, void* color) + #ifdef WORDS_BIGENDIAN + memcpy(color, in, sizeof(UINT16)); + #else +- UINT16* out = color; +- out[0] = in[1] + (in[0]<<8); ++ UINT16 out = in[1] + (in[0]<<8); ++ memcpy(color, &out, sizeof(out)); + #endif + } + +@@ -125,8 +125,8 @@ get_pixel_32L(Imaging im, int x, int y, void* color) + { + UINT8* in = (UINT8*) &im->image[y][x*4]; + #ifdef WORDS_BIGENDIAN +- INT32* out = color; +- out[0] = in[0] + (in[1]<<8) + (in[2]<<16) + (in[3]<<24); ++ INT32 out = in[0] + (in[1]<<8) + (in[2]<<16) + (in[3]<<24); ++ memcpy(color, &out, sizeof(out)); + #else + memcpy(color, in, sizeof(INT32)); + #endif +@@ -139,8 +139,8 @@ get_pixel_32B(Imaging im, int x, int y, void* color) + #ifdef WORDS_BIGENDIAN + memcpy(color, in, sizeof(INT32)); + #else +- INT32* out = color; +- out[0] = in[3] + (in[2]<<8) + (in[1]<<16) + (in[0]<<24); ++ INT32 out = in[3] + (in[2]<<8) + (in[1]<<16) + (in[0]<<24); ++ memcpy(color, &out, sizeof(out)); + #endif + } + +diff --git a/src/libImaging/Bands.c b/src/libImaging/Bands.c +index e38e228..7fff044 100644 +--- a/src/libImaging/Bands.c ++++ b/src/libImaging/Bands.c +@@ -50,7 +50,8 @@ ImagingGetBand(Imaging imIn, int band) + UINT8* out = imOut->image8[y]; + x = 0; + for (; x < imIn->xsize - 3; x += 4) { +- *((UINT32*) (out + x)) = MAKE_UINT32(in[0], in[4], in[8], in[12]); ++ UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]); ++ memcpy(out + x, &v, sizeof(v)); + in += 16; + } + for (; x < imIn->xsize; x++) { +@@ -98,8 +99,10 @@ ImagingSplit(Imaging imIn, Imaging bands[4]) + UINT8* out1 = bands[1]->image8[y]; + x = 0; + for (; x < imIn->xsize - 3; x += 4) { +- *((UINT32*) (out0 + x)) = MAKE_UINT32(in[0], in[4], in[8], in[12]); +- *((UINT32*) (out1 + x)) = MAKE_UINT32(in[0+3], in[4+3], in[8+3], in[12+3]); ++ UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]); ++ memcpy(out0 + x, &v, sizeof(v)); ++ v = MAKE_UINT32(in[0+3], in[4+3], in[8+3], in[12+3]); ++ memcpy(out1 + x, &v, sizeof(v)); + in += 16; + } + for (; x < imIn->xsize; x++) { +@@ -116,9 +119,12 @@ ImagingSplit(Imaging imIn, Imaging bands[4]) + UINT8* out2 = bands[2]->image8[y]; + x = 0; + for (; x < imIn->xsize - 3; x += 4) { +- *((UINT32*) (out0 + x)) = MAKE_UINT32(in[0], in[4], in[8], in[12]); +- *((UINT32*) (out1 + x)) = MAKE_UINT32(in[0+1], in[4+1], in[8+1], in[12+1]); +- *((UINT32*) (out2 + x)) = MAKE_UINT32(in[0+2], in[4+2], in[8+2], in[12+2]); ++ UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]); ++ memcpy(out0 + x, &v, sizeof(v)); ++ v = MAKE_UINT32(in[0+1], in[4+1], in[8+1], in[12+1]); ++ memcpy(out1 + x, &v, sizeof(v)); ++ v = MAKE_UINT32(in[0+2], in[4+2], in[8+2], in[12+2]); ++ memcpy(out2 + x, &v, sizeof(v)); + in += 16; + } + for (; x < imIn->xsize; x++) { +@@ -137,10 +143,14 @@ ImagingSplit(Imaging imIn, Imaging bands[4]) + UINT8* out3 = bands[3]->image8[y]; + x = 0; + for (; x < imIn->xsize - 3; x += 4) { +- *((UINT32*) (out0 + x)) = MAKE_UINT32(in[0], in[4], in[8], in[12]); +- *((UINT32*) (out1 + x)) = MAKE_UINT32(in[0+1], in[4+1], in[8+1], in[12+1]); +- *((UINT32*) (out2 + x)) = MAKE_UINT32(in[0+2], in[4+2], in[8+2], in[12+2]); +- *((UINT32*) (out3 + x)) = MAKE_UINT32(in[0+3], in[4+3], in[8+3], in[12+3]); ++ UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]); ++ memcpy(out0 + x, &v, sizeof(v)); ++ v = MAKE_UINT32(in[0+1], in[4+1], in[8+1], in[12+1]); ++ memcpy(out1 + x, &v, sizeof(v)); ++ v = MAKE_UINT32(in[0+2], in[4+2], in[8+2], in[12+2]); ++ memcpy(out2 + x, &v, sizeof(v)); ++ v = MAKE_UINT32(in[0+3], in[4+3], in[8+3], in[12+3]); ++ memcpy(out3 + x, &v, sizeof(v)); + in += 16; + } + for (; x < imIn->xsize; x++) { +diff --git a/src/libImaging/ColorLUT.c b/src/libImaging/ColorLUT.c +index 46b0014..f01d389 100644 +--- a/src/libImaging/ColorLUT.c ++++ b/src/libImaging/ColorLUT.c +@@ -105,7 +105,7 @@ ImagingColorLUT3D_linear(Imaging imOut, Imaging imIn, int table_channels, + ImagingSectionEnter(&cookie); + for (y = 0; y < imOut->ysize; y++) { + UINT8* rowIn = (UINT8 *)imIn->image[y]; +- UINT32* rowOut = (UINT32 *)imOut->image[y]; ++ char* rowOut = (char *)imOut->image[y]; + for (x = 0; x < imOut->xsize; x++) { + UINT32 index1D = rowIn[x*4 + 0] * scale1D; + UINT32 index2D = rowIn[x*4 + 1] * scale2D; +@@ -120,6 +120,7 @@ ImagingColorLUT3D_linear(Imaging imOut, Imaging imIn, int table_channels, + INT16 leftleft[4], leftright[4], rightleft[4], rightright[4]; + + if (table_channels == 3) { ++ UINT32 v; + interpolate3(leftleft, &table[idx + 0], &table[idx + 3], shift1D); + interpolate3(leftright, &table[idx + size1D*3], + &table[idx + size1D*3 + 3], shift1D); +@@ -133,12 +134,14 @@ ImagingColorLUT3D_linear(Imaging imOut, Imaging imIn, int table_channels, + + interpolate3(result, left, right, shift3D); + +- rowOut[x] = MAKE_UINT32( ++ v = MAKE_UINT32( + clip8(result[0]), clip8(result[1]), + clip8(result[2]), rowIn[x*4 + 3]); ++ memcpy(rowOut + x * sizeof(v), &v, sizeof(v)); + } + + if (table_channels == 4) { ++ UINT32 v; + interpolate4(leftleft, &table[idx + 0], &table[idx + 4], shift1D); + interpolate4(leftright, &table[idx + size1D*4], + &table[idx + size1D*4 + 4], shift1D); +@@ -152,9 +155,10 @@ ImagingColorLUT3D_linear(Imaging imOut, Imaging imIn, int table_channels, + + interpolate4(result, left, right, shift3D); + +- rowOut[x] = MAKE_UINT32( ++ v = MAKE_UINT32( + clip8(result[0]), clip8(result[1]), + clip8(result[2]), clip8(result[3])); ++ memcpy(rowOut + x * sizeof(v), &v, sizeof(v)); + } + } + } +diff --git a/src/libImaging/Convert.c b/src/libImaging/Convert.c +index 39ddf87..b7b6a80 100644 +--- a/src/libImaging/Convert.c ++++ b/src/libImaging/Convert.c +@@ -229,42 +229,46 @@ static void + rgb2i(UINT8* out_, const UINT8* in, int xsize) + { + int x; +- INT32* out = (INT32*) out_; +- for (x = 0; x < xsize; x++, in += 4) +- *out++ = L24(in) >> 16; ++ for (x = 0; x < xsize; x++, in += 4, out_ += 4) { ++ INT32 v = L24(in) >> 16; ++ memcpy(out_, &v, sizeof(v)); ++ } + } + + static void + rgb2f(UINT8* out_, const UINT8* in, int xsize) + { + int x; +- FLOAT32* out = (FLOAT32*) out_; +- for (x = 0; x < xsize; x++, in += 4) +- *out++ = (float) L(in) / 1000.0F; ++ for (x = 0; x < xsize; x++, in += 4, out_ += 4) { ++ FLOAT32 v = (float) L(in) / 1000.0F; ++ memcpy(out_, &v, sizeof(v)); ++ } + } + + static void + rgb2bgr15(UINT8* out_, const UINT8* in, int xsize) + { + int x; +- UINT16* out = (UINT16*) out_; +- for (x = 0; x < xsize; x++, in += 4) +- *out++ = ++ for (x = 0; x < xsize; x++, in += 4, out_ += 2) { ++ UINT16 v = + ((((UINT16)in[0])<<7)&0x7c00) + + ((((UINT16)in[1])<<2)&0x03e0) + + ((((UINT16)in[2])>>3)&0x001f); ++ memcpy(out_, &v, sizeof(v)); ++ } + } + + static void + rgb2bgr16(UINT8* out_, const UINT8* in, int xsize) + { + int x; +- UINT16* out = (UINT16*) out_; +- for (x = 0; x < xsize; x++, in += 4) +- *out++ = ++ for (x = 0; x < xsize; x++, in += 4, out_ += 2) { ++ UINT16 v = + ((((UINT16)in[0])<<8)&0xf800) + + ((((UINT16)in[1])<<3)&0x07e0) + + ((((UINT16)in[2])>>3)&0x001f); ++ memcpy(out_, &v, sizeof(v)); ++ } + } + + static void +@@ -490,12 +494,13 @@ rgbT2rgba(UINT8* out, int xsize, int r, int g, int b) + UINT32 repl = trns & 0x00ffffff; + #endif + +- UINT32* tmp = (UINT32 *)out; + int i; + +- for (i=0; i < xsize; i++ ,tmp++) { +- if (tmp[0]==trns) { +- tmp[0]=repl; ++ for (i=0; i < xsize; i++ ,out += sizeof(trns)) { ++ UINT32 v; ++ memcpy(&v, out, sizeof(v)); ++ if (v==trns) { ++ memcpy(out, &repl, sizeof(repl)); + } + } + } +@@ -553,32 +558,35 @@ static void + bit2i(UINT8* out_, const UINT8* in, int xsize) + { + int x; +- INT32* out = (INT32*) out_; +- for (x = 0; x < xsize; x++) +- *out++ = (*in++ != 0) ? 255 : 0; ++ for (x = 0; x < xsize; x++, out_ += 4) { ++ INT32 v = (*in++ != 0) ? 255 : 0; ++ memcpy(out_, &v, sizeof(v)); ++ } + } + + static void + l2i(UINT8* out_, const UINT8* in, int xsize) + { + int x; +- INT32* out = (INT32*) out_; +- for (x = 0; x < xsize; x++) +- *out++ = (INT32) *in++; ++ for (x = 0; x < xsize; x++, out_ += 4) { ++ INT32 v = *in++; ++ memcpy(out_, &v, sizeof(v)); ++ } + } + + static void + i2l(UINT8* out, const UINT8* in_, int xsize) + { + int x; +- INT32* in = (INT32*) in_; +- for (x = 0; x < xsize; x++, in++, out++) { +- if (*in <= 0) ++ for (x = 0; x < xsize; x++, out++, in_ += 4) { ++ INT32 v; ++ memcpy(&v, in_, sizeof(v)); ++ if (v <= 0) + *out = 0; +- else if (*in >= 255) ++ else if (v >= 255) + *out = 255; + else +- *out = (UINT8) *in; ++ *out = (UINT8) v; + } + } + +@@ -586,10 +594,13 @@ static void + i2f(UINT8* out_, const UINT8* in_, int xsize) + { + int x; +- INT32* in = (INT32*) in_; +- FLOAT32* out = (FLOAT32*) out_; +- for (x = 0; x < xsize; x++) +- *out++ = (FLOAT32) *in++; ++ for (x = 0; x < xsize; x++, in_ += 4, out_ += 4) { ++ INT32 i; ++ FLOAT32 f; ++ memcpy(&i, in_, sizeof(i)); ++ f = i; ++ memcpy(out_, &f, sizeof(f)); ++ } + } + + /* ------------- */ +@@ -600,32 +611,35 @@ static void + bit2f(UINT8* out_, const UINT8* in, int xsize) + { + int x; +- FLOAT32* out = (FLOAT32*) out_; +- for (x = 0; x < xsize; x++) +- *out++ = (*in++ != 0) ? 255.0F : 0.0F; ++ for (x = 0; x < xsize; x++, out_ += 4) { ++ FLOAT32 f = (*in++ != 0) ? 255.0F : 0.0F; ++ memcpy(out_, &f, sizeof(f)); ++ } + } + + static void + l2f(UINT8* out_, const UINT8* in, int xsize) + { + int x; +- FLOAT32* out = (FLOAT32*) out_; +- for (x = 0; x < xsize; x++) +- *out++ = (FLOAT32) *in++; ++ for (x = 0; x < xsize; x++, out_ += 4) { ++ FLOAT32 f = (FLOAT32) *in++; ++ memcpy(out_, &f, sizeof(f)); ++ } + } + + static void + f2l(UINT8* out, const UINT8* in_, int xsize) + { + int x; +- FLOAT32* in = (FLOAT32*) in_; +- for (x = 0; x < xsize; x++, in++, out++) { +- if (*in <= 0.0) ++ for (x = 0; x < xsize; x++, out++, in_ += 4) { ++ FLOAT32 v; ++ memcpy(&v, in_, sizeof(v)); ++ if (v <= 0.0) + *out = 0; +- else if (*in >= 255.0) ++ else if (v >= 255.0) + *out = 255; + else +- *out = (UINT8) *in; ++ *out = (UINT8) v; + } + } + +@@ -633,10 +647,13 @@ static void + f2i(UINT8* out_, const UINT8* in_, int xsize) + { + int x; +- FLOAT32* in = (FLOAT32*) in_; +- INT32* out = (INT32*) out_; +- for (x = 0; x < xsize; x++) +- *out++ = (INT32) *in++; ++ for (x = 0; x < xsize; x++, in_ += 4, out_ += 4) { ++ FLOAT32 f; ++ INT32 i; ++ memcpy(&f, in_, sizeof(f)); ++ i = f; ++ memcpy(out_, &i, sizeof(i)); ++ } + } + + /* ----------------- */ +@@ -673,9 +690,10 @@ static void + I_I16L(UINT8* out, const UINT8* in_, int xsize) + { + int x, v; +- INT32* in = (INT32*) in_; +- for (x = 0; x < xsize; x++, in++) { +- v = CLIP16(*in); ++ for (x = 0; x < xsize; x++, in_ += 4) { ++ INT32 i; ++ memcpy(&i, in_, sizeof(i)); ++ v = CLIP16(i); + *out++ = (UINT8) v; + *out++ = (UINT8) (v >> 8); + } +@@ -685,9 +703,10 @@ static void + I_I16B(UINT8* out, const UINT8* in_, int xsize) + { + int x, v; +- INT32* in = (INT32*) in_; +- for (x = 0; x < xsize; x++, in++) { +- v = CLIP16(*in); ++ for (x = 0; x < xsize; x++, in_ += 4) { ++ INT32 i; ++ memcpy(&i, in_, sizeof(i)); ++ v = CLIP16(i); + *out++ = (UINT8) (v >> 8); + *out++ = (UINT8) v; + } +@@ -698,9 +717,10 @@ static void + I16L_I(UINT8* out_, const UINT8* in, int xsize) + { + int x; +- INT32* out = (INT32*) out_; +- for (x = 0; x < xsize; x++, in += 2) +- *out++ = in[0] + ((int) in[1] << 8); ++ for (x = 0; x < xsize; x++, in += 2, out_ += 4) { ++ INT32 v = in[0] + ((int) in[1] << 8); ++ memcpy(out_, &v, sizeof(v)); ++ } + } + + +@@ -708,18 +728,20 @@ static void + I16B_I(UINT8* out_, const UINT8* in, int xsize) + { + int x; +- INT32* out = (INT32*) out_; +- for (x = 0; x < xsize; x++, in += 2) +- *out++ = in[1] + ((int) in[0] << 8); ++ for (x = 0; x < xsize; x++, in += 2, out_ += 4) { ++ INT32 v = in[1] + ((int) in[0] << 8); ++ memcpy(out_, &v, sizeof(v)); ++ } + } + + static void + I16L_F(UINT8* out_, const UINT8* in, int xsize) + { + int x; +- FLOAT32* out = (FLOAT32*) out_; +- for (x = 0; x < xsize; x++, in += 2) +- *out++ = (FLOAT32) (in[0] + ((int) in[1] << 8)); ++ for (x = 0; x < xsize; x++, in += 2, out_ += 4) { ++ FLOAT32 v = in[0] + ((int) in[1] << 8); ++ memcpy(out_, &v, sizeof(v)); ++ } + } + + +@@ -727,9 +749,10 @@ static void + I16B_F(UINT8* out_, const UINT8* in, int xsize) + { + int x; +- FLOAT32* out = (FLOAT32*) out_; +- for (x = 0; x < xsize; x++, in += 2) +- *out++ = (FLOAT32) (in[1] + ((int) in[0] << 8)); ++ for (x = 0; x < xsize; x++, in += 2, out_ += 4) { ++ FLOAT32 v = in[1] + ((int) in[0] << 8); ++ memcpy(out_, &v, sizeof(v)); ++ } + } + + static void +@@ -930,18 +953,20 @@ static void + p2i(UINT8* out_, const UINT8* in, int xsize, const UINT8* palette) + { + int x; +- INT32* out = (INT32*) out_; +- for (x = 0; x < xsize; x++) +- *out++ = L(&palette[in[x]*4]) / 1000; ++ for (x = 0; x < xsize; x++, in += 2, out_ += 4) { ++ INT32 v = L(&palette[in[x]*4]) / 1000; ++ memcpy(out_, &v, sizeof(v)); ++ } + } + + static void + p2f(UINT8* out_, const UINT8* in, int xsize, const UINT8* palette) + { + int x; +- FLOAT32* out = (FLOAT32*) out_; +- for (x = 0; x < xsize; x++) +- *out++ = (float) L(&palette[in[x]*4]) / 1000.0F; ++ for (x = 0; x < xsize; x++, in += 2, out_ += 4) { ++ FLOAT32 v = L(&palette[in[x]*4]) / 1000.0F; ++ memcpy(out_, &v, sizeof(v)); ++ } + } + + static void +diff --git a/src/libImaging/Filter.c b/src/libImaging/Filter.c +index 64010ee..b033abf 100644 +--- a/src/libImaging/Filter.c ++++ b/src/libImaging/Filter.c +@@ -122,26 +122,29 @@ ImagingFilter3x3(Imaging imOut, Imaging im, const float* kernel, + UINT8* in_1 = (UINT8*) im->image[y-1]; + UINT8* in0 = (UINT8*) im->image[y]; + UINT8* in1 = (UINT8*) im->image[y+1]; +- UINT32* out = (UINT32*) imOut->image[y]; ++ UINT8* out = (UINT8*) imOut->image[y]; + + memcpy(out, in0, sizeof(UINT32)); + if (im->bands == 2) { + for (x = 1; x < im->xsize-1; x++) { + float ss0 = offset; + float ss3 = offset; ++ UINT32 v; + ss0 += KERNEL1x3(in1, x*4+0, &kernel[0], 4); + ss3 += KERNEL1x3(in1, x*4+3, &kernel[0], 4); + ss0 += KERNEL1x3(in0, x*4+0, &kernel[3], 4); + ss3 += KERNEL1x3(in0, x*4+3, &kernel[3], 4); + ss0 += KERNEL1x3(in_1, x*4+0, &kernel[6], 4); + ss3 += KERNEL1x3(in_1, x*4+3, &kernel[6], 4); +- out[x] = MAKE_UINT32(clip8(ss0), 0, 0, clip8(ss3)); ++ v = MAKE_UINT32(clip8(ss0), 0, 0, clip8(ss3)); ++ memcpy(out + x * sizeof(v), &v, sizeof(v)); + } + } else if (im->bands == 3) { + for (x = 1; x < im->xsize-1; x++) { + float ss0 = offset; + float ss1 = offset; + float ss2 = offset; ++ UINT32 v; + ss0 += KERNEL1x3(in1, x*4+0, &kernel[0], 4); + ss1 += KERNEL1x3(in1, x*4+1, &kernel[0], 4); + ss2 += KERNEL1x3(in1, x*4+2, &kernel[0], 4); +@@ -151,8 +154,9 @@ ImagingFilter3x3(Imaging imOut, Imaging im, const float* kernel, + ss0 += KERNEL1x3(in_1, x*4+0, &kernel[6], 4); + ss1 += KERNEL1x3(in_1, x*4+1, &kernel[6], 4); + ss2 += KERNEL1x3(in_1, x*4+2, &kernel[6], 4); +- out[x] = MAKE_UINT32( ++ v = MAKE_UINT32( + clip8(ss0), clip8(ss1), clip8(ss2), 0); ++ memcpy(out + x * sizeof(v), &v, sizeof(v)); + } + } else if (im->bands == 4) { + for (x = 1; x < im->xsize-1; x++) { +@@ -160,6 +164,7 @@ ImagingFilter3x3(Imaging imOut, Imaging im, const float* kernel, + float ss1 = offset; + float ss2 = offset; + float ss3 = offset; ++ UINT32 v; + ss0 += KERNEL1x3(in1, x*4+0, &kernel[0], 4); + ss1 += KERNEL1x3(in1, x*4+1, &kernel[0], 4); + ss2 += KERNEL1x3(in1, x*4+2, &kernel[0], 4); +@@ -172,11 +177,12 @@ ImagingFilter3x3(Imaging imOut, Imaging im, const float* kernel, + ss1 += KERNEL1x3(in_1, x*4+1, &kernel[6], 4); + ss2 += KERNEL1x3(in_1, x*4+2, &kernel[6], 4); + ss3 += KERNEL1x3(in_1, x*4+3, &kernel[6], 4); +- out[x] = MAKE_UINT32( ++ v = MAKE_UINT32( + clip8(ss0), clip8(ss1), clip8(ss2), clip8(ss3)); ++ memcpy(out + x * sizeof(v), &v, sizeof(v)); + } + } +- out[x] = ((UINT32*) in0)[x]; ++ memcpy(out + x * sizeof(UINT32), in0 + x * sizeof(UINT32), sizeof(UINT32)); + } + } + memcpy(imOut->image[y], im->image[y], im->linesize); +@@ -232,13 +238,14 @@ ImagingFilter5x5(Imaging imOut, Imaging im, const float* kernel, + UINT8* in0 = (UINT8*) im->image[y]; + UINT8* in1 = (UINT8*) im->image[y+1]; + UINT8* in2 = (UINT8*) im->image[y+2]; +- UINT32* out = (UINT32*) imOut->image[y]; ++ UINT8* out = (UINT8*) imOut->image[y]; + + memcpy(out, in0, sizeof(UINT32) * 2); + if (im->bands == 2) { + for (x = 2; x < im->xsize-2; x++) { + float ss0 = offset; + float ss3 = offset; ++ UINT32 v; + ss0 += KERNEL1x5(in2, x*4+0, &kernel[0], 4); + ss3 += KERNEL1x5(in2, x*4+3, &kernel[0], 4); + ss0 += KERNEL1x5(in1, x*4+0, &kernel[5], 4); +@@ -249,13 +256,15 @@ ImagingFilter5x5(Imaging imOut, Imaging im, const float* kernel, + ss3 += KERNEL1x5(in_1, x*4+3, &kernel[15], 4); + ss0 += KERNEL1x5(in_2, x*4+0, &kernel[20], 4); + ss3 += KERNEL1x5(in_2, x*4+3, &kernel[20], 4); +- out[x] = MAKE_UINT32(clip8(ss0), 0, 0, clip8(ss3)); ++ v = MAKE_UINT32(clip8(ss0), 0, 0, clip8(ss3)); ++ memcpy(out + x * sizeof(v), &v, sizeof(v)); + } + } else if (im->bands == 3) { + for (x = 2; x < im->xsize-2; x++) { + float ss0 = offset; + float ss1 = offset; + float ss2 = offset; ++ UINT32 v; + ss0 += KERNEL1x5(in2, x*4+0, &kernel[0], 4); + ss1 += KERNEL1x5(in2, x*4+1, &kernel[0], 4); + ss2 += KERNEL1x5(in2, x*4+2, &kernel[0], 4); +@@ -271,8 +280,9 @@ ImagingFilter5x5(Imaging imOut, Imaging im, const float* kernel, + ss0 += KERNEL1x5(in_2, x*4+0, &kernel[20], 4); + ss1 += KERNEL1x5(in_2, x*4+1, &kernel[20], 4); + ss2 += KERNEL1x5(in_2, x*4+2, &kernel[20], 4); +- out[x] = MAKE_UINT32( ++ v = MAKE_UINT32( + clip8(ss0), clip8(ss1), clip8(ss2), 0); ++ memcpy(out + x * sizeof(v), &v, sizeof(v)); + } + } else if (im->bands == 4) { + for (x = 2; x < im->xsize-2; x++) { +@@ -280,6 +290,7 @@ ImagingFilter5x5(Imaging imOut, Imaging im, const float* kernel, + float ss1 = offset; + float ss2 = offset; + float ss3 = offset; ++ UINT32 v; + ss0 += KERNEL1x5(in2, x*4+0, &kernel[0], 4); + ss1 += KERNEL1x5(in2, x*4+1, &kernel[0], 4); + ss2 += KERNEL1x5(in2, x*4+2, &kernel[0], 4); +@@ -300,12 +311,12 @@ ImagingFilter5x5(Imaging imOut, Imaging im, const float* kernel, + ss1 += KERNEL1x5(in_2, x*4+1, &kernel[20], 4); + ss2 += KERNEL1x5(in_2, x*4+2, &kernel[20], 4); + ss3 += KERNEL1x5(in_2, x*4+3, &kernel[20], 4); +- out[x] = MAKE_UINT32( ++ v = MAKE_UINT32( + clip8(ss0), clip8(ss1), clip8(ss2), clip8(ss3)); ++ memcpy(out + x * sizeof(v), &v, sizeof(v)); + } + } +- out[x] = ((UINT32*) in0)[x]; +- out[x+1] = ((UINT32*) in0)[x+1]; ++ memcpy(out + x * sizeof(UINT32), in0 + x * sizeof(UINT32), sizeof(UINT32) * 2); + } + } + memcpy(imOut->image[y], im->image[y], im->linesize); +diff --git a/src/libImaging/Geometry.c b/src/libImaging/Geometry.c +index 56a1aa3..cd64763 100644 +--- a/src/libImaging/Geometry.c ++++ b/src/libImaging/Geometry.c +@@ -396,7 +396,7 @@ nearest_filter16(void* out, Imaging im, double xin, double yin) + int y = COORD(yin); + if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) + return 0; +- ((INT16*)out)[0] = ((INT16*)(im->image8[y]))[x]; ++ memcpy(out, im->image8[y] + x * sizeof(INT16), sizeof(INT16)); + return 1; + } + +@@ -457,18 +457,22 @@ bilinear_filter8(void* out, Imaging im, double xin, double yin) + static int + bilinear_filter32I(void* out, Imaging im, double xin, double yin) + { ++ INT32 k; + BILINEAR_HEAD(INT32); + BILINEAR_BODY(INT32, im->image32, 1, 0); +- ((INT32*)out)[0] = (INT32) v1; ++ k = v1; ++ memcpy(out, &k, sizeof(k)); + return 1; + } + + static int + bilinear_filter32F(void* out, Imaging im, double xin, double yin) + { ++ FLOAT32 k; + BILINEAR_HEAD(FLOAT32); + BILINEAR_BODY(FLOAT32, im->image32, 1, 0); +- ((FLOAT32*)out)[0] = (FLOAT32) v1; ++ k = v1; ++ memcpy(out, &k, sizeof(k)); + return 1; + } + +@@ -569,18 +573,22 @@ bicubic_filter8(void* out, Imaging im, double xin, double yin) + static int + bicubic_filter32I(void* out, Imaging im, double xin, double yin) + { ++ INT32 k; + BICUBIC_HEAD(INT32); + BICUBIC_BODY(INT32, im->image32, 1, 0); +- ((INT32*)out)[0] = (INT32) v1; ++ k = v1; ++ memcpy(out, &k, sizeof(k)); + return 1; + } + + static int + bicubic_filter32F(void* out, Imaging im, double xin, double yin) + { ++ FLOAT32 k; + BICUBIC_HEAD(FLOAT32); + BICUBIC_BODY(FLOAT32, im->image32, 1, 0); +- ((FLOAT32*)out)[0] = (FLOAT32) v1; ++ k = v1; ++ memcpy(out, &k, sizeof(k)); + return 1; + } + +diff --git a/src/libImaging/GetBBox.c b/src/libImaging/GetBBox.c +index 5cfb795..b63888f 100644 +--- a/src/libImaging/GetBBox.c ++++ b/src/libImaging/GetBBox.c +@@ -147,7 +147,7 @@ ImagingGetExtrema(Imaging im, void *extrema) + } + } + memcpy(extrema, &imin, sizeof(imin)); +- ((INT32*) extrema)[1] = imax; ++ memcpy(((char*)extrema) + sizeof(imin), &imax, sizeof(imax)); + break; + case IMAGING_TYPE_FLOAT32: + fmin = fmax = ((FLOAT32*) im->image32[0])[0]; +@@ -161,22 +161,26 @@ ImagingGetExtrema(Imaging im, void *extrema) + } + } + memcpy(extrema, &fmin, sizeof(fmin)); +- ((FLOAT32*) extrema)[1] = fmax; ++ memcpy(((char*)extrema) + sizeof(fmin), &fmax, sizeof(fmax)); + break; + case IMAGING_TYPE_SPECIAL: + if (strcmp(im->mode, "I;16") == 0) { +- imin = imax = ((UINT16*) im->image8[0])[0]; ++ UINT16 v; ++ memcpy(&v, *im->image8, sizeof(v)); ++ imin = imax = v; + for (y = 0; y < im->ysize; y++) { +- UINT16* in = (UINT16 *) im->image[y]; + for (x = 0; x < im->xsize; x++) { +- if (imin > in[x]) +- imin = in[x]; +- else if (imax < in[x]) +- imax = in[x]; ++ memcpy(&v, im->image[y] + x * sizeof(v), sizeof(v)); ++ if (imin > v) ++ imin = v; ++ else if (imax < v) ++ imax = v; + } + } +- ((UINT16*) extrema)[0] = (UINT16) imin; +- ((UINT16*) extrema)[1] = (UINT16) imax; ++ v = (UINT16) imin; ++ memcpy(extrema, &v, sizeof(v)); ++ v = (UINT16) imax; ++ memcpy(((char*)extrema) + sizeof(v), &v, sizeof(v)); + break; + } + /* FALL THROUGH */ +diff --git a/src/libImaging/Histo.c b/src/libImaging/Histo.c +index 887f09a..fb992e3 100644 +--- a/src/libImaging/Histo.c ++++ b/src/libImaging/Histo.c +@@ -125,7 +125,7 @@ ImagingGetHistogram(Imaging im, Imaging imMask, void* minmax) + if (!im->xsize || !im->ysize) + break; + memcpy(&imin, minmax, sizeof(imin)); +- imax = ((INT32*) minmax)[1]; ++ memcpy(&imax, ((char*)minmax) + sizeof(imin), sizeof(imax)); + if (imin >= imax) + break; + ImagingSectionEnter(&cookie); +@@ -146,7 +146,7 @@ ImagingGetHistogram(Imaging im, Imaging imMask, void* minmax) + if (!im->xsize || !im->ysize) + break; + memcpy(&fmin, minmax, sizeof(fmin)); +- fmax = ((FLOAT32*) minmax)[1]; ++ memcpy(&fmax, ((char*)minmax) + sizeof(fmin), sizeof(fmax)); + if (fmin >= fmax) + break; + ImagingSectionEnter(&cookie); +diff --git a/src/libImaging/Pack.c b/src/libImaging/Pack.c +index 5c298c6..d18f31c 100644 +--- a/src/libImaging/Pack.c ++++ b/src/libImaging/Pack.c +@@ -252,7 +252,7 @@ ImagingPackRGB(UINT8* out, const UINT8* in, int pixels) + int i = 0; + /* RGB triplets */ + for (; i < pixels-1; i++) { +- ((UINT32*)out)[0] = ((UINT32*)in)[i]; ++ memcpy(out, in + i * 4, 4); + out += 3; + } + for (; i < pixels; i++) { +@@ -392,18 +392,19 @@ static void + packI16B(UINT8* out, const UINT8* in_, int pixels) + { + int i; +- INT32* in = (INT32*) in_; + UINT16 tmp_; + UINT8* tmp = (UINT8*) &tmp_; + for (i = 0; i < pixels; i++) { +- if (in[0] <= 0) ++ INT32 in; ++ memcpy(&in, in_, sizeof(in)); ++ if (in <= 0) + tmp_ = 0; +- else if (in[0] > 65535) ++ else if (in > 65535) + tmp_ = 65535; + else +- tmp_ = in[0]; ++ tmp_ = in; + C16B; +- out += 2; in++; ++ out += 2; in_ += sizeof(in); + } + } + +diff --git a/src/libImaging/Point.c b/src/libImaging/Point.c +index 426c410..9b4bf6b 100644 +--- a/src/libImaging/Point.c ++++ b/src/libImaging/Point.c +@@ -99,12 +99,12 @@ im_point_8_32(Imaging imOut, Imaging imIn, im_point_context* context) + { + int x, y; + /* 8-bit source, 32-bit destination */ +- INT32* table = (INT32*) context->table; ++ char* table = (char*) context->table; + for (y = 0; y < imIn->ysize; y++) { + UINT8* in = imIn->image8[y]; + INT32* out = imOut->image32[y]; + for (x = 0; x < imIn->xsize; x++) +- out[x] = table[in[x]]; ++ memcpy(out + x, table + in[x] * sizeof(INT32), sizeof(INT32)); + } + } + +@@ -242,11 +242,15 @@ ImagingPointTransform(Imaging imIn, double scale, double offset) + if (strcmp(imIn->mode,"I;16") == 0) { + ImagingSectionEnter(&cookie); + for (y = 0; y < imIn->ysize; y++) { +- UINT16* in = (UINT16 *)imIn->image[y]; +- UINT16* out = (UINT16 *)imOut->image[y]; ++ char* in = (char*)imIn->image[y]; ++ char* out = (char*)imOut->image[y]; + /* FIXME: add clipping? */ +- for (x = 0; x < imIn->xsize; x++) +- out[x] = in[x] * scale + offset; ++ for (x = 0; x < imIn->xsize; x++) { ++ UINT16 v; ++ memcpy(&v, in + x * sizeof(v), sizeof(v)); ++ v = v * scale + offset; ++ memcpy(out + x * sizeof(UINT16), &v, sizeof(v)); ++ } + } + ImagingSectionLeave(&cookie); + break; +diff --git a/src/libImaging/Resample.c b/src/libImaging/Resample.c +index 6fae208..d1a89e2 100644 +--- a/src/libImaging/Resample.c ++++ b/src/libImaging/Resample.c +@@ -304,6 +304,7 @@ ImagingResampleHorizontal_8bpc(Imaging imOut, Imaging imIn, int offset, + if (imIn->bands == 2) { + for (yy = 0; yy < imOut->ysize; yy++) { + for (xx = 0; xx < imOut->xsize; xx++) { ++ UINT32 v; + xmin = bounds[xx * 2 + 0]; + xmax = bounds[xx * 2 + 1]; + k = &kk[xx * ksize]; +@@ -312,13 +313,14 @@ ImagingResampleHorizontal_8bpc(Imaging imOut, Imaging imIn, int offset, + ss0 += ((UINT8) imIn->image[yy + offset][(x + xmin)*4 + 0]) * k[x]; + ss3 += ((UINT8) imIn->image[yy + offset][(x + xmin)*4 + 3]) * k[x]; + } +- ((UINT32 *) imOut->image[yy])[xx] = MAKE_UINT32( +- clip8(ss0), 0, 0, clip8(ss3)); ++ v = MAKE_UINT32(clip8(ss0), 0, 0, clip8(ss3)); ++ memcpy(imOut->image[yy] + xx * sizeof(v), &v, sizeof(v)); + } + } + } else if (imIn->bands == 3) { + for (yy = 0; yy < imOut->ysize; yy++) { + for (xx = 0; xx < imOut->xsize; xx++) { ++ UINT32 v; + xmin = bounds[xx * 2 + 0]; + xmax = bounds[xx * 2 + 1]; + k = &kk[xx * ksize]; +@@ -328,13 +330,14 @@ ImagingResampleHorizontal_8bpc(Imaging imOut, Imaging imIn, int offset, + ss1 += ((UINT8) imIn->image[yy + offset][(x + xmin)*4 + 1]) * k[x]; + ss2 += ((UINT8) imIn->image[yy + offset][(x + xmin)*4 + 2]) * k[x]; + } +- ((UINT32 *) imOut->image[yy])[xx] = MAKE_UINT32( +- clip8(ss0), clip8(ss1), clip8(ss2), 0); ++ v = MAKE_UINT32(clip8(ss0), clip8(ss1), clip8(ss2), 0); ++ memcpy(imOut->image[yy] + xx * sizeof(v), &v, sizeof(v)); + } + } + } else { + for (yy = 0; yy < imOut->ysize; yy++) { + for (xx = 0; xx < imOut->xsize; xx++) { ++ UINT32 v; + xmin = bounds[xx * 2 + 0]; + xmax = bounds[xx * 2 + 1]; + k = &kk[xx * ksize]; +@@ -345,8 +348,8 @@ ImagingResampleHorizontal_8bpc(Imaging imOut, Imaging imIn, int offset, + ss2 += ((UINT8) imIn->image[yy + offset][(x + xmin)*4 + 2]) * k[x]; + ss3 += ((UINT8) imIn->image[yy + offset][(x + xmin)*4 + 3]) * k[x]; + } +- ((UINT32 *) imOut->image[yy])[xx] = MAKE_UINT32( +- clip8(ss0), clip8(ss1), clip8(ss2), clip8(ss3)); ++ v = MAKE_UINT32(clip8(ss0), clip8(ss1), clip8(ss2), clip8(ss3)); ++ memcpy(imOut->image[yy] + xx * sizeof(v), &v, sizeof(v)); + } + } + } +@@ -388,13 +391,14 @@ ImagingResampleVertical_8bpc(Imaging imOut, Imaging imIn, int offset, + ymin = bounds[yy * 2 + 0]; + ymax = bounds[yy * 2 + 1]; + for (xx = 0; xx < imOut->xsize; xx++) { ++ UINT32 v; + ss0 = ss3 = 1 << (PRECISION_BITS -1); + for (y = 0; y < ymax; y++) { + ss0 += ((UINT8) imIn->image[y + ymin][xx*4 + 0]) * k[y]; + ss3 += ((UINT8) imIn->image[y + ymin][xx*4 + 3]) * k[y]; + } +- ((UINT32 *) imOut->image[yy])[xx] = MAKE_UINT32( +- clip8(ss0), 0, 0, clip8(ss3)); ++ v = MAKE_UINT32(clip8(ss0), 0, 0, clip8(ss3)); ++ memcpy(imOut->image[yy] + xx * sizeof(v), &v, sizeof(v)); + } + } + } else if (imIn->bands == 3) { +@@ -403,14 +407,15 @@ ImagingResampleVertical_8bpc(Imaging imOut, Imaging imIn, int offset, + ymin = bounds[yy * 2 + 0]; + ymax = bounds[yy * 2 + 1]; + for (xx = 0; xx < imOut->xsize; xx++) { ++ UINT32 v; + ss0 = ss1 = ss2 = 1 << (PRECISION_BITS -1); + for (y = 0; y < ymax; y++) { + ss0 += ((UINT8) imIn->image[y + ymin][xx*4 + 0]) * k[y]; + ss1 += ((UINT8) imIn->image[y + ymin][xx*4 + 1]) * k[y]; + ss2 += ((UINT8) imIn->image[y + ymin][xx*4 + 2]) * k[y]; + } +- ((UINT32 *) imOut->image[yy])[xx] = MAKE_UINT32( +- clip8(ss0), clip8(ss1), clip8(ss2), 0); ++ v = MAKE_UINT32(clip8(ss0), clip8(ss1), clip8(ss2), 0); ++ memcpy(imOut->image[yy] + xx * sizeof(v), &v, sizeof(v)); + } + } + } else { +@@ -419,6 +424,7 @@ ImagingResampleVertical_8bpc(Imaging imOut, Imaging imIn, int offset, + ymin = bounds[yy * 2 + 0]; + ymax = bounds[yy * 2 + 1]; + for (xx = 0; xx < imOut->xsize; xx++) { ++ UINT32 v; + ss0 = ss1 = ss2 = ss3 = 1 << (PRECISION_BITS -1); + for (y = 0; y < ymax; y++) { + ss0 += ((UINT8) imIn->image[y + ymin][xx*4 + 0]) * k[y]; +@@ -426,8 +432,8 @@ ImagingResampleVertical_8bpc(Imaging imOut, Imaging imIn, int offset, + ss2 += ((UINT8) imIn->image[y + ymin][xx*4 + 2]) * k[y]; + ss3 += ((UINT8) imIn->image[y + ymin][xx*4 + 3]) * k[y]; + } +- ((UINT32 *) imOut->image[yy])[xx] = MAKE_UINT32( +- clip8(ss0), clip8(ss1), clip8(ss2), clip8(ss3)); ++ v = MAKE_UINT32(clip8(ss0), clip8(ss1), clip8(ss2), clip8(ss3)); ++ memcpy(imOut->image[yy] + xx * sizeof(v), &v, sizeof(v)); + } + } + } +diff --git a/src/libImaging/SgiRleDecode.c b/src/libImaging/SgiRleDecode.c +index 39e7b3a..70b0ec5 100644 +--- a/src/libImaging/SgiRleDecode.c ++++ b/src/libImaging/SgiRleDecode.c +@@ -56,15 +56,15 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z) + return 0; + } + +-static int expandrow2(UINT16* dest, UINT16* src, int n, int z) ++static int expandrow2(UINT8* dest, const UINT8* src, int n, int z) + { + UINT8 pixel, count; + + + for (;n > 0; n--) + { +- pixel = ((UINT8*)src)[1]; +- ++src; ++ pixel = src[1]; ++ src+=2; + if (n == 1 && pixel != 0) + return n; + count = pixel & RLE_MAX_RUN; +@@ -72,16 +72,17 @@ static int expandrow2(UINT16* dest, UINT16* src, int n, int z) + return count; + if (pixel & RLE_COPY_FLAG) { + while(count--) { +- *dest = *src++; +- dest += z; ++ memcpy(dest, src, 2); ++ src += 2; ++ dest += z * 2; + } + } + else { + while (count--) { +- *dest = *src; +- dest += z; ++ memcpy(dest, src, 2); ++ dest += z * 2; + } +- ++src; ++ src+=2; + } + } + return 0; +@@ -167,7 +168,7 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, + goto sgi_finish_decode; + } + else { +- if(expandrow2((UINT16*)&state->buffer[c->channo * 2], (UINT16*)&ptr[c->rleoffset], c->rlelength, im->bands)) ++ if(expandrow2(&state->buffer[c->channo * 2], &ptr[c->rleoffset], c->rlelength, im->bands)) + goto sgi_finish_decode; + } + +diff --git a/src/libImaging/Unpack.c b/src/libImaging/Unpack.c +index cdaba6e..485f984 100644 +--- a/src/libImaging/Unpack.c ++++ b/src/libImaging/Unpack.c +@@ -32,7 +32,6 @@ + + #include "Imaging.h" + +- + #define R 0 + #define G 1 + #define B 2 +@@ -327,11 +326,11 @@ static void + unpackLA(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + /* LA, pixel interleaved */ + for (i = 0; i < pixels; i++) { +- out[i] = MAKE_UINT32(in[0], in[0], in[0], in[1]); +- in += 2; ++ UINT32 iv = MAKE_UINT32(in[0], in[0], in[0], in[1]); ++ memcpy(_out, &iv, sizeof(iv)); ++ in += 2; _out += 4; + } + } + +@@ -339,10 +338,10 @@ static void + unpackLAL(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + /* LA, line interleaved */ +- for (i = 0; i < pixels; i++) { +- out[i] = MAKE_UINT32(in[i], in[i], in[i], in[i+pixels]); ++ for (i = 0; i < pixels; i++, _out+=4) { ++ UINT32 iv = MAKE_UINT32(in[i], in[i], in[i], in[i+pixels]); ++ memcpy(_out, &iv, sizeof(iv)); + } + } + +@@ -480,15 +479,18 @@ void + ImagingUnpackRGB(UINT8* _out, const UINT8* in, int pixels) + { + int i = 0; +- UINT32* out = (UINT32*) _out; + /* RGB triplets */ + for (; i < pixels-1; i++) { +- out[i] = MASK_UINT32_CHANNEL_3 | *(UINT32*)&in[0]; +- in += 3; ++ UINT32 iv; ++ memcpy(&iv, in, sizeof(iv)); ++ iv |= MASK_UINT32_CHANNEL_3; ++ memcpy(_out, &iv, sizeof(iv)); ++ in += 3; _out += 4; + } + for (; i < pixels; i++) { +- out[i] = MAKE_UINT32(in[0], in[1], in[2], 255); +- in += 3; ++ UINT32 iv = MAKE_UINT32(in[0], in[1], in[2], 255); ++ memcpy(_out, &iv, sizeof(iv)); ++ in += 3; _out += 4; + } + } + +@@ -496,11 +498,11 @@ void + unpackRGB16L(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + /* 16-bit RGB triplets, little-endian order */ + for (i = 0; i < pixels; i++) { +- out[i] = MAKE_UINT32(in[1], in[3], in[5], 255); +- in += 6; ++ UINT32 iv = MAKE_UINT32(in[1], in[3], in[5], 255); ++ memcpy(_out, &iv, sizeof(iv)); ++ in += 6; _out += 4; + } + } + +@@ -508,11 +510,11 @@ void + unpackRGB16B(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + /* 16-bit RGB triplets, big-endian order */ + for (i = 0; i < pixels; i++) { +- out[i] = MAKE_UINT32(in[0], in[2], in[4], 255); +- in += 6; ++ UINT32 iv = MAKE_UINT32(in[0], in[2], in[4], 255); ++ memcpy(_out, &iv, sizeof(iv)); ++ in += 6; _out += 4; + } + } + +@@ -520,10 +522,10 @@ static void + unpackRGBL(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + /* RGB, line interleaved */ +- for (i = 0; i < pixels; i++) { +- out[i] = MAKE_UINT32(in[i], in[i+pixels], in[i+pixels+pixels], 255); ++ for (i = 0; i < pixels; i++, _out+=4) { ++ UINT32 iv = MAKE_UINT32(in[i], in[i+pixels], in[i+pixels+pixels], 255); ++ memcpy(_out, &iv, sizeof(iv)); + } + } + +@@ -531,12 +533,12 @@ static void + unpackRGBR(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + /* RGB, bit reversed */ + for (i = 0; i < pixels; i++) { +- out[i] = MAKE_UINT32(BITFLIP[in[0]], BITFLIP[in[1]], +- BITFLIP[in[2]], 255); +- in += 3; ++ UINT32 iv = MAKE_UINT32(BITFLIP[in[0]], BITFLIP[in[1]], ++ BITFLIP[in[2]], 255); ++ memcpy(_out, &iv, sizeof(iv)); ++ in += 3; _out += 4; + } + } + +@@ -544,11 +546,11 @@ void + ImagingUnpackBGR(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + /* RGB, reversed bytes */ + for (i = 0; i < pixels; i++) { +- out[i] = MAKE_UINT32(in[2], in[1], in[0], 255); +- in += 3; ++ UINT32 iv = MAKE_UINT32(in[2], in[1], in[0], 255); ++ memcpy(_out, &iv, sizeof(iv)); ++ in += 3; _out += 4; + } + } + +@@ -676,11 +678,11 @@ static void + ImagingUnpackBGRX(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + /* RGB, reversed bytes with padding */ + for (i = 0; i < pixels; i++) { +- out[i] = MAKE_UINT32(in[2], in[1], in[0], 255); +- in += 4; ++ UINT32 iv = MAKE_UINT32(in[2], in[1], in[0], 255); ++ memcpy(_out, &iv, sizeof(iv)); ++ in += 4; _out += 4; + } + } + +@@ -688,11 +690,11 @@ static void + ImagingUnpackXRGB(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + /* RGB, leading pad */ + for (i = 0; i < pixels; i++) { +- out[i] = MAKE_UINT32(in[1], in[2], in[3], 255); +- in += 4; ++ UINT32 iv = MAKE_UINT32(in[1], in[2], in[3], 255); ++ memcpy(_out, &iv, sizeof(iv)); ++ in += 4; _out += 4; + } + } + +@@ -700,11 +702,11 @@ static void + ImagingUnpackXBGR(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + /* RGB, reversed bytes, leading pad */ + for (i = 0; i < pixels; i++) { +- out[i] = MAKE_UINT32(in[3], in[2], in[1], 255); +- in += 4; ++ UINT32 iv = MAKE_UINT32(in[3], in[2], in[1], 255); ++ memcpy(_out, &iv, sizeof(iv)); ++ in += 4; _out += 4; + } + } + +@@ -714,11 +716,11 @@ static void + unpackRGBALA(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + /* greyscale with alpha */ + for (i = 0; i < pixels; i++) { +- out[i] = MAKE_UINT32(in[0], in[0], in[0], in[1]); +- in += 2; ++ UINT32 iv = MAKE_UINT32(in[0], in[0], in[0], in[1]); ++ memcpy(_out, &iv, sizeof(iv)); ++ in += 2; _out += 4; + } + } + +@@ -726,11 +728,11 @@ static void + unpackRGBALA16B(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + /* 16-bit greyscale with alpha, big-endian */ + for (i = 0; i < pixels; i++) { +- out[i] = MAKE_UINT32(in[0], in[0], in[0], in[2]); +- in += 4; ++ UINT32 iv = MAKE_UINT32(in[0], in[0], in[0], in[2]); ++ memcpy(_out, &iv, sizeof(iv)); ++ in += 4; _out += 4; + } + } + +@@ -738,20 +740,21 @@ static void + unpackRGBa16L(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + /* premultiplied 16-bit RGBA, little-endian */ + for (i = 0; i < pixels; i++) { + int a = in[7]; ++ UINT32 iv; + if ( ! a) { +- out[i] = 0; ++ iv = 0; + } else if (a == 255) { +- out[i] = MAKE_UINT32(in[1], in[3], in[5], a); ++ iv = MAKE_UINT32(in[1], in[3], in[5], a); + } else { +- out[i] = MAKE_UINT32(CLIP8(in[1] * 255 / a), +- CLIP8(in[3] * 255 / a), +- CLIP8(in[5] * 255 / a), a); ++ iv = MAKE_UINT32(CLIP8(in[1] * 255 / a), ++ CLIP8(in[3] * 255 / a), ++ CLIP8(in[5] * 255 / a), a); + } +- in += 8; ++ memcpy(_out, &iv, sizeof(iv)); ++ in += 8; _out += 4; + } + } + +@@ -759,20 +762,21 @@ static void + unpackRGBa16B(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + /* premultiplied 16-bit RGBA, big-endian */ + for (i = 0; i < pixels; i++) { + int a = in[6]; ++ UINT32 iv; + if ( ! a) { +- out[i] = 0; ++ iv = 0; + } else if (a == 255) { +- out[i] = MAKE_UINT32(in[0], in[2], in[4], a); ++ iv = MAKE_UINT32(in[0], in[2], in[4], a); + } else { +- out[i] = MAKE_UINT32(CLIP8(in[0] * 255 / a), +- CLIP8(in[2] * 255 / a), +- CLIP8(in[4] * 255 / a), a); ++ iv = MAKE_UINT32(CLIP8(in[0] * 255 / a), ++ CLIP8(in[2] * 255 / a), ++ CLIP8(in[4] * 255 / a), a); + } +- in += 8; ++ memcpy(_out, &iv, sizeof(iv)); ++ in += 8; _out += 4; + } + } + +@@ -780,20 +784,21 @@ static void + unpackRGBa(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + /* premultiplied RGBA */ + for (i = 0; i < pixels; i++) { + int a = in[3]; ++ UINT32 iv; + if ( ! a) { +- out[i] = 0; ++ iv = 0; + } else if (a == 255) { +- out[i] = MAKE_UINT32(in[0], in[1], in[2], a); ++ iv = MAKE_UINT32(in[0], in[1], in[2], a); + } else { +- out[i] = MAKE_UINT32(CLIP8(in[0] * 255 / a), +- CLIP8(in[1] * 255 / a), +- CLIP8(in[2] * 255 / a), a); ++ iv = MAKE_UINT32(CLIP8(in[0] * 255 / a), ++ CLIP8(in[1] * 255 / a), ++ CLIP8(in[2] * 255 / a), a); + } +- in += 4; ++ memcpy(_out, &iv, sizeof(iv)); ++ in += 4; _out += 4; + } + } + +@@ -843,20 +848,21 @@ static void + unpackBGRa(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + /* premultiplied BGRA */ + for (i = 0; i < pixels; i++) { + int a = in[3]; ++ UINT32 iv; + if ( ! a) { +- out[i] = 0; ++ iv = 0; + } else if (a == 255) { +- out[i] = MAKE_UINT32(in[2], in[1], in[0], a); ++ iv = MAKE_UINT32(in[2], in[1], in[0], a); + } else { +- out[i] = MAKE_UINT32(CLIP8(in[2] * 255 / a), +- CLIP8(in[1] * 255 / a), +- CLIP8(in[0] * 255 / a), a); ++ iv = MAKE_UINT32(CLIP8(in[2] * 255 / a), ++ CLIP8(in[1] * 255 / a), ++ CLIP8(in[0] * 255 / a), a); + } +- in += 4; ++ memcpy(_out, &iv, sizeof(iv)); ++ in += 4; _out += 4; + } + } + +@@ -878,11 +884,11 @@ static void + unpackRGBAL(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + /* RGBA, line interleaved */ +- for (i = 0; i < pixels; i++) { +- out[i] = MAKE_UINT32(in[i], in[i+pixels], in[i+pixels+pixels], +- in[i+pixels+pixels+pixels]); ++ for (i = 0; i < pixels; i++, _out+=4) { ++ UINT32 iv = MAKE_UINT32(in[i], in[i+pixels], in[i+pixels+pixels], ++ in[i+pixels+pixels+pixels]); ++ memcpy(_out, &iv, sizeof(iv)); + } + } + +@@ -890,10 +896,10 @@ void + unpackRGBA16L(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + /* 16-bit RGBA, little-endian order */ +- for (i = 0; i < pixels; i++) { +- out[i] = MAKE_UINT32(in[1], in[3], in[5], in[7]); ++ for (i = 0; i < pixels; i++, _out+=4) { ++ UINT32 iv = MAKE_UINT32(in[1], in[3], in[5], in[7]); ++ memcpy(_out, &iv, sizeof(iv)); + in += 8; + } + } +@@ -902,10 +908,10 @@ void + unpackRGBA16B(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + /* 16-bit RGBA, big-endian order */ +- for (i = 0; i < pixels; i++) { +- out[i] = MAKE_UINT32(in[0], in[2], in[4], in[6]); ++ for (i = 0; i < pixels; i++, _out+=4) { ++ UINT32 iv = MAKE_UINT32(in[0], in[2], in[4], in[6]); ++ memcpy(_out, &iv, sizeof(iv)); + in += 8; + } + } +@@ -914,11 +920,11 @@ static void + unpackARGB(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + /* RGBA, leading pad */ + for (i = 0; i < pixels; i++) { +- out[i] = MAKE_UINT32(in[1], in[2], in[3], in[0]); +- in += 4; ++ UINT32 iv = MAKE_UINT32(in[1], in[2], in[3], in[0]); ++ memcpy(_out, &iv, sizeof(iv)); ++ in += 4; _out += 4; + } + } + +@@ -926,11 +932,11 @@ static void + unpackABGR(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + /* RGBA, reversed bytes */ + for (i = 0; i < pixels; i++) { +- out[i] = MAKE_UINT32(in[3], in[2], in[1], in[0]); +- in += 4; ++ UINT32 iv = MAKE_UINT32(in[3], in[2], in[1], in[0]); ++ memcpy(_out, &iv, sizeof(iv)); ++ in += 4; _out += 4; + } + } + +@@ -938,11 +944,11 @@ static void + unpackBGRA(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + /* RGBA, reversed bytes */ + for (i = 0; i < pixels; i++) { +- out[i] = MAKE_UINT32(in[2], in[1], in[0], in[3]); +- in += 4; ++ UINT32 iv = MAKE_UINT32(in[2], in[1], in[0], in[3]); ++ memcpy(_out, &iv, sizeof(iv)); ++ in += 4; _out += 4; + } + } + +@@ -953,11 +959,11 @@ static void + unpackCMYKI(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + /* CMYK, inverted bytes (Photoshop 2.5) */ + for (i = 0; i < pixels; i++) { +- out[i] = ~MAKE_UINT32(in[0], in[1], in[2], in[3]); +- in += 4; ++ UINT32 iv = ~MAKE_UINT32(in[0], in[1], in[2], in[3]); ++ memcpy(_out, &iv, sizeof(iv)); ++ in += 4; _out += 4; + } + } + +@@ -1031,7 +1037,6 @@ unpackI12_I16(UINT8* out, const UINT8* in, int pixels){ + #ifdef WORDS_BIGENDIAN + UINT8* tmp = (UINT8 *)&pixel; + #endif +- UINT16* out16 = (UINT16 *)out; + for (i = 0; i < pixels-1; i+=2) { + pixel = (((UINT16) in[0]) << 4 ) + (in[1] >>4); + #ifdef WORDS_BIGENDIAN +@@ -1040,14 +1045,15 @@ unpackI12_I16(UINT8* out, const UINT8* in, int pixels){ + memcpy(out, &pixel, sizeof(pixel)); + #endif + ++ out+=2; + pixel = (((UINT16) (in[1] & 0x0F)) << 8) + in[2]; + #ifdef WORDS_BIGENDIAN +- out[2] = tmp[1]; out[3] = tmp[0]; ++ out[0] = tmp[1]; out[1] = tmp[0]; + #else +- out16[1] = pixel; ++ memcpy(out, &pixel, sizeof(pixel)); + #endif + +- in += 3; out16 += 2; out+=4; ++ in += 3; out+=2; + } + if (i == pixels-1) { + pixel = (((UINT16) in[0]) << 4 ) + (in[1] >>4); +@@ -1085,10 +1091,9 @@ static void + copy4skip1(UINT8* _out, const UINT8* in, int pixels) + { + int i; +- UINT32* out = (UINT32*) _out; + for (i = 0; i < pixels; i++) { +- out[i] = *(UINT32*)&in[0]; +- in += 5; ++ memcpy(_out, in, 4); ++ in += 5; _out += 4; + } + } + +@@ -1098,8 +1103,8 @@ copy4skip2(UINT8* _out, const UINT8* in, int pixels) + int i; + UINT32* out = (UINT32*) _out; + for (i = 0; i < pixels; i++) { +- out[i] = *(UINT32*)&in[0]; +- in += 6; ++ memcpy(_out, in, 4); ++ in += 6; _out += 4; + } + } + +-- +2.27.0 + diff --git a/pre-CVE-2020-11538-2.patch b/pre-CVE-2020-11538-2.patch new file mode 100644 index 0000000000000000000000000000000000000000..44a8468ac66c7f940754c22b71070fe2ea8a29e3 --- /dev/null +++ b/pre-CVE-2020-11538-2.patch @@ -0,0 +1,82 @@ +From be44f0d9923485f3ed3a7a9fd479cf8cf69d814a Mon Sep 17 00:00:00 2001 +From: Andrew Murray +Date: Wed, 1 Jan 2020 14:16:45 +1100 +Subject: [PATCH] Catch SGI buffer overruns + +--- + Tests/test_image.py | 2 ++ + src/libImaging/SgiRleDecode.c | 23 +++++++++++++++++------ + 4 files changed, 19 insertions(+), 6 deletions(-) + +diff --git a/src/libImaging/SgiRleDecode.c b/src/libImaging/SgiRleDecode.c +index 70b0ec5..e9b2c0b 100644 +--- a/src/libImaging/SgiRleDecode.c ++++ b/src/libImaging/SgiRleDecode.c +@@ -25,7 +25,7 @@ static void read4B(UINT32* dest, UINT8* buf) + *dest = (UINT32)((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]); + } + +-static int expandrow(UINT8* dest, UINT8* src, int n, int z) ++static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize) + { + UINT8 pixel, count; + +@@ -37,6 +37,9 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z) + count = pixel & RLE_MAX_RUN; + if (!count) + return count; ++ if (count > xsize){ ++ return -1; ++ } + if (pixel & RLE_COPY_FLAG) { + while(count--) { + *dest = *src++; +@@ -56,7 +59,7 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z) + return 0; + } + +-static int expandrow2(UINT8* dest, const UINT8* src, int n, int z) ++static int expandrow2(UINT8* dest, const UINT8* src, int n, int z, int xsize) + { + UINT8 pixel, count; + +@@ -70,6 +73,9 @@ static int expandrow2(UINT8* dest, const UINT8* src, int n, int z) + count = pixel & RLE_MAX_RUN; + if (!count) + return count; ++ if (count > xsize){ ++ return -1; ++ } + if (pixel & RLE_COPY_FLAG) { + while(count--) { + memcpy(dest, src, 2); +@@ -96,6 +102,7 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, + UINT8 *ptr; + SGISTATE *c; + int err = 0; ++ int status; + + /* Get all data from File descriptor */ + c = (SGISTATE*)state->context; +@@ -164,13 +171,17 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, + + /* row decompression */ + if (c->bpc ==1) { +- if(expandrow(&state->buffer[c->channo], &ptr[c->rleoffset], c->rlelength, im->bands)) +- goto sgi_finish_decode; ++ status = expandrow(&state->buffer[c->channo], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize); + } + else { +- if(expandrow2(&state->buffer[c->channo * 2], &ptr[c->rleoffset], c->rlelength, im->bands)) +- goto sgi_finish_decode; ++ status = expandrow2(&state->buffer[c->channo * 2], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize); + } ++ if (status == -1) { ++ state->errcode = IMAGING_CODEC_OVERRUN; ++ return -1; ++ } else if (status == 1) { ++ goto sgi_finish_decode; ++ } + + state->count += c->rlelength; + } diff --git a/python-pillow.spec b/python-pillow.spec index 3f3c5171135b261c9e0e9ff7362ebefe74adf953..99c7a1d0c9d65bdbe133b69d7725db301eaef2ec 100644 --- a/python-pillow.spec +++ b/python-pillow.spec @@ -5,7 +5,7 @@ Name: python-pillow Version: 5.3.0 -Release: 5 +Release: 6 Summary: Python image processing library License: MIT URL: http://python-pillow.github.io/ @@ -15,6 +15,13 @@ Patch0000: 0000-CVE-2019-16865-1.patch Patch0001: 0001-CVE-2019-16865-2.patch Patch0002: 0002-CVE-2019-16865-3.patch Patch0003: 0003-CVE-2019-16865-4.patch +Patch0004: CVE-2020-10378.patch +Patch0005: CVE-2020-10177.patch +Patch0006: CVE-2020-10994.patch +Patch0007: replace_copy_operations_with_memcpy.patch +Patch0008: pre-CVE-2020-11538-1.patch +Patch0009: pre-CVE-2020-11538-2.patch +Patch0010: CVE-2020-11538.patch BuildRequires: freetype-devel ghostscript lcms2-devel libimagequant-devel libjpeg-devel BuildRequires: libtiff-devel libwebp-devel openjpeg2-devel tk-devel zlib-devel @@ -168,6 +175,12 @@ popd %doc docs/_build_py3/html %changelog +* Wed Nov 25 2020 shixuantong - 5.3.0-6 +- Type:cves +- ID:CVE-2020-11538 CVE-2020-10378 CVE-2020-10177 CVE-2020-10994 +- SUG:NA +- DESC:fix CVE-2020-11538 CVE-2020-10378 CVE-2020-10177 CVE-2020-10994 + * Fri Aug 21 2020 shixuantong - 5.3.0-5 - add release version for rebuild diff --git a/replace_copy_operations_with_memcpy.patch b/replace_copy_operations_with_memcpy.patch new file mode 100644 index 0000000000000000000000000000000000000000..809a6ff177c2b977272bbbbe672cfb7972466606 --- /dev/null +++ b/replace_copy_operations_with_memcpy.patch @@ -0,0 +1,257 @@ +From 220bfee19a98a0d5b3fe5a52b51df16dd459c397 Mon Sep 17 00:00:00 2001 +From: Rolf Eike Beer +Date: Fri, 29 Jun 2018 22:33:08 +0200 +Subject: [PATCH] replace copy operations with memcpy() + +https://github.com/python-pillow/Pillow/commit/220bfee19a98a0d5b3fe5a52b51df16dd459c397 + +This replaces trivial instances where a copy from one pointer to the other +involves no further calculations or casts. The compiler will optimize this to +whatever the platform offers. +--- + src/libImaging/Access.c | 35 +++++++++++++---------------------- + src/libImaging/Draw.c | 3 +-- + src/libImaging/Filter.c | 5 ++--- + src/libImaging/Geometry.c | 2 +- + src/libImaging/GetBBox.c | 4 ++-- + src/libImaging/Histo.c | 4 ++-- + src/libImaging/Unpack.c | 4 ++-- + 7 files changed, 23 insertions(+), 34 deletions(-) + +diff --git a/src/libImaging/Access.c b/src/libImaging/Access.c +index 292968f..8d27a0a 100644 +--- a/src/libImaging/Access.c ++++ b/src/libImaging/Access.c +@@ -94,11 +94,11 @@ static void + get_pixel_16L(Imaging im, int x, int y, void* color) + { + UINT8* in = (UINT8*) &im->image[y][x+x]; +- UINT16* out = color; + #ifdef WORDS_BIGENDIAN ++ UINT16* out = color; + out[0] = in[0] + (in[1]<<8); + #else +- out[0] = *(UINT16*) in; ++ memcpy(color, in, sizeof(UINT16)); + #endif + } + +@@ -106,10 +106,10 @@ static void + get_pixel_16B(Imaging im, int x, int y, void* color) + { + UINT8* in = (UINT8*) &im->image[y][x+x]; +- UINT16* out = color; + #ifdef WORDS_BIGENDIAN +- out[0] = *(UINT16*) in; ++ memcpy(color, in, sizeof(UINT16)); + #else ++ UINT16* out = color; + out[0] = in[1] + (in[0]<<8); + #endif + } +@@ -117,19 +117,18 @@ get_pixel_16B(Imaging im, int x, int y, void* color) + static void + get_pixel_32(Imaging im, int x, int y, void* color) + { +- INT32* out = color; +- out[0] = im->image32[y][x]; ++ memcpy(color, &im->image32[y][x], sizeof(INT32)); + } + + static void + get_pixel_32L(Imaging im, int x, int y, void* color) + { + UINT8* in = (UINT8*) &im->image[y][x*4]; +- INT32* out = color; + #ifdef WORDS_BIGENDIAN ++ INT32* out = color; + out[0] = in[0] + (in[1]<<8) + (in[2]<<16) + (in[3]<<24); + #else +- out[0] = *(INT32*) in; ++ memcpy(color, in, sizeof(INT32)); + #endif + } + +@@ -137,10 +136,10 @@ static void + get_pixel_32B(Imaging im, int x, int y, void* color) + { + UINT8* in = (UINT8*) &im->image[y][x*4]; +- INT32* out = color; + #ifdef WORDS_BIGENDIAN +- out[0] = *(INT32*) in; ++ memcpy(color, in, sizeof(INT32)); + #else ++ INT32* out = color; + out[0] = in[3] + (in[2]<<8) + (in[1]<<16) + (in[0]<<24); + #endif + } +@@ -153,7 +152,7 @@ put_pixel(Imaging im, int x, int y, const void* color) + if (im->image8) + im->image8[y][x] = *((UINT8*) color); + else +- im->image32[y][x] = *((INT32*) color); ++ memcpy(&im->image32[y][x], color, sizeof(INT32)); + } + + static void +@@ -165,10 +164,7 @@ put_pixel_8(Imaging im, int x, int y, const void* color) + static void + put_pixel_16L(Imaging im, int x, int y, const void* color) + { +- const char* in = color; +- UINT8* out = (UINT8*) &im->image8[y][x+x]; +- out[0] = in[0]; +- out[1] = in[1]; ++ memcpy(&im->image8[y][x+x], color, 2); + } + + static void +@@ -183,12 +179,7 @@ put_pixel_16B(Imaging im, int x, int y, const void* color) + static void + put_pixel_32L(Imaging im, int x, int y, const void* color) + { +- const char* in = color; +- UINT8* out = (UINT8*) &im->image8[y][x*4]; +- out[0] = in[0]; +- out[1] = in[1]; +- out[2] = in[2]; +- out[3] = in[3]; ++ memcpy(&im->image8[y][x*4], color, 4); + } + + static void +@@ -205,7 +196,7 @@ put_pixel_32B(Imaging im, int x, int y, const void* color) + static void + put_pixel_32(Imaging im, int x, int y, const void* color) + { +- im->image32[y][x] = *((INT32*) color); ++ memcpy(&im->image32[y][x], color, sizeof(INT32)); + } + + void +diff --git a/src/libImaging/Draw.c b/src/libImaging/Draw.c +index d0f374f..3b1ae0c 100644 +--- a/src/libImaging/Draw.c ++++ b/src/libImaging/Draw.c +@@ -40,7 +40,6 @@ + #define FLOOR(v) ((v) >= 0.0 ? (int) (v) : (int) floor(v)) + + #define INK8(ink) (*(UINT8*)ink) +-#define INK32(ink) (*(INT32*)ink) + + /* + * Rounds around zero (up=away from zero, down=torwards zero) +@@ -555,7 +554,7 @@ DRAW draw32rgba = { point32rgba, hline32rgba, line32rgba, polygon32rgba }; + ink = INK8(ink_);\ + } else {\ + draw = (op) ? &draw32rgba : &draw32; \ +- ink = INK32(ink_);\ ++ memcpy(&ink, ink_, sizeof(ink)); \ + } + + int +diff --git a/src/libImaging/Filter.c b/src/libImaging/Filter.c +index 6e4a005..64010ee 100644 +--- a/src/libImaging/Filter.c ++++ b/src/libImaging/Filter.c +@@ -124,7 +124,7 @@ ImagingFilter3x3(Imaging imOut, Imaging im, const float* kernel, + UINT8* in1 = (UINT8*) im->image[y+1]; + UINT32* out = (UINT32*) imOut->image[y]; + +- out[0] = ((UINT32*) in0)[0]; ++ memcpy(out, in0, sizeof(UINT32)); + if (im->bands == 2) { + for (x = 1; x < im->xsize-1; x++) { + float ss0 = offset; +@@ -234,8 +234,7 @@ ImagingFilter5x5(Imaging imOut, Imaging im, const float* kernel, + UINT8* in2 = (UINT8*) im->image[y+2]; + UINT32* out = (UINT32*) imOut->image[y]; + +- out[0] = ((UINT32*) in0)[0]; +- out[1] = ((UINT32*) in0)[1]; ++ memcpy(out, in0, sizeof(UINT32) * 2); + if (im->bands == 2) { + for (x = 2; x < im->xsize-2; x++) { + float ss0 = offset; +diff --git a/src/libImaging/Geometry.c b/src/libImaging/Geometry.c +index 1d08728..56a1aa3 100644 +--- a/src/libImaging/Geometry.c ++++ b/src/libImaging/Geometry.c +@@ -407,7 +407,7 @@ nearest_filter32(void* out, Imaging im, double xin, double yin) + int y = COORD(yin); + if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) + return 0; +- ((INT32*)out)[0] = im->image32[y][x]; ++ memcpy(out, &im->image32[y][x], sizeof(INT32)); + return 1; + } + +diff --git a/src/libImaging/GetBBox.c b/src/libImaging/GetBBox.c +index 3cfa42c..5cfb795 100644 +--- a/src/libImaging/GetBBox.c ++++ b/src/libImaging/GetBBox.c +@@ -146,7 +146,7 @@ ImagingGetExtrema(Imaging im, void *extrema) + imax = in[x]; + } + } +- ((INT32*) extrema)[0] = imin; ++ memcpy(extrema, &imin, sizeof(imin)); + ((INT32*) extrema)[1] = imax; + break; + case IMAGING_TYPE_FLOAT32: +@@ -160,7 +160,7 @@ ImagingGetExtrema(Imaging im, void *extrema) + fmax = in[x]; + } + } +- ((FLOAT32*) extrema)[0] = fmin; ++ memcpy(extrema, &fmin, sizeof(fmin)); + ((FLOAT32*) extrema)[1] = fmax; + break; + case IMAGING_TYPE_SPECIAL: +diff --git a/src/libImaging/Histo.c b/src/libImaging/Histo.c +index 0bfc8df..887f09a 100644 +--- a/src/libImaging/Histo.c ++++ b/src/libImaging/Histo.c +@@ -124,7 +124,7 @@ ImagingGetHistogram(Imaging im, Imaging imMask, void* minmax) + return ImagingError_ValueError("min/max not given"); + if (!im->xsize || !im->ysize) + break; +- imin = ((INT32*) minmax)[0]; ++ memcpy(&imin, minmax, sizeof(imin)); + imax = ((INT32*) minmax)[1]; + if (imin >= imax) + break; +@@ -145,7 +145,7 @@ ImagingGetHistogram(Imaging im, Imaging imMask, void* minmax) + return ImagingError_ValueError("min/max not given"); + if (!im->xsize || !im->ysize) + break; +- fmin = ((FLOAT32*) minmax)[0]; ++ memcpy(&fmin, minmax, sizeof(fmin)); + fmax = ((FLOAT32*) minmax)[1]; + if (fmin >= fmax) + break; +diff --git a/src/libImaging/Unpack.c b/src/libImaging/Unpack.c +index e9921d2..cdaba6e 100644 +--- a/src/libImaging/Unpack.c ++++ b/src/libImaging/Unpack.c +@@ -1037,7 +1037,7 @@ unpackI12_I16(UINT8* out, const UINT8* in, int pixels){ + #ifdef WORDS_BIGENDIAN + out[0] = tmp[1]; out[1] = tmp[0]; + #else +- out16[0] = pixel; ++ memcpy(out, &pixel, sizeof(pixel)); + #endif + + pixel = (((UINT16) (in[1] & 0x0F)) << 8) + in[2]; +@@ -1054,7 +1054,7 @@ unpackI12_I16(UINT8* out, const UINT8* in, int pixels){ + #ifdef WORDS_BIGENDIAN + out[0] = tmp[1]; out[1] = tmp[0]; + #else +- out16[0] = pixel; ++ memcpy(out, &pixel, sizeof(pixel)); + #endif + } + } +-- +2.27.0 +