Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use explicit memcpy() to avoid unaligned memory accesses #3225

Merged
merged 2 commits into from Jul 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 20 additions & 11 deletions src/_imaging.c
Expand Up @@ -382,7 +382,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;

Expand Down Expand Up @@ -416,19 +417,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;
}
}
Expand Down Expand Up @@ -532,6 +533,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 */
Expand Down Expand Up @@ -597,14 +600,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) {
Expand Down Expand Up @@ -799,15 +804,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 */
Expand Down
43 changes: 17 additions & 26 deletions src/libImaging/Access.c
Expand Up @@ -94,54 +94,53 @@ 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
out[0] = in[0] + (in[1]<<8);
UINT16 out = in[0] + (in[1]<<8);
memcpy(color, &out, sizeof(out));
#else
out[0] = *(UINT16*) in;
memcpy(color, in, sizeof(UINT16));
#endif
}

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
out[0] = in[1] + (in[0]<<8);
UINT16 out = in[1] + (in[0]<<8);
memcpy(color, &out, sizeof(out));
#endif
}

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
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
out[0] = *(INT32*) in;
memcpy(color, in, sizeof(INT32));
#endif
}

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
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
}

Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
30 changes: 20 additions & 10 deletions src/libImaging/Bands.c
Expand Up @@ -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++) {
Expand Down Expand Up @@ -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++) {
Expand All @@ -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++) {
Expand All @@ -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++) {
Expand Down
10 changes: 7 additions & 3 deletions src/libImaging/ColorLUT.c
Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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));
}
}
}
Expand Down