[gegl] buffer: verify alignment in optimized buffer_set/get paths
- From: N/A <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] buffer: verify alignment in optimized buffer_set/get paths
- Date: Wed, 14 Mar 2018 09:57:38 +0000 (UTC)
commit 54519440f74e60380b93c744ec1a0fe73ad58e50
Author: Ell <ell_se yahoo com>
Date: Wed Mar 14 05:19:35 2018 -0400
buffer: verify alignment in optimized buffer_set/get paths
In the optimized cases of gegl_buffer_iterate_write() and
gegl_buffer_iterate_read_simple(), make sure all read/write
accesses to the buffer and the tile are properly aligned for the
used type, and fall back to the generic version otherwise.
On some architectures, unaligned access can lead to a crash; see
bug #793682.
gegl/buffer/gegl-buffer-access.c | 84 ++++++++++++++++++++++++++++++++++++++
1 files changed, 84 insertions(+), 0 deletions(-)
---
diff --git a/gegl/buffer/gegl-buffer-access.c b/gegl/buffer/gegl-buffer-access.c
index 93335cf..d33d06a 100644
--- a/gegl/buffer/gegl-buffer-access.c
+++ b/gegl/buffer/gegl-buffer-access.c
@@ -489,9 +489,35 @@ with multi-threading - and should be added back later.
else
{
int lskip_offset = lskip * px_size;
+
+ #ifdef __GNUC__
+ #define CHECK_ALIGNMENT_ALIGNOF __alignof__
+ #else
+ #define CHECK_ALIGNMENT_ALIGNOF(type) \
+ (G_STRUCT_OFFSET (struct alignof_helper, b))
+ #endif
+ #define CHECK_ALIGNMENT(type) \
+ do \
+ { \
+ struct alignof_helper { char a; type b; }; \
+ /* verify 'alignof (type)' is a power of 2 */ \
+ G_STATIC_ASSERT (! (CHECK_ALIGNMENT_ALIGNOF (type) & \
+ (CHECK_ALIGNMENT_ALIGNOF (type) - 1)));\
+ if ((((uintptr_t) tp + lskip_offset) | \
+ ((uintptr_t) bp + lskip_offset) | \
+ tile_stride | \
+ buf_stride) & \
+ (CHECK_ALIGNMENT_ALIGNOF (type) - 1)) \
+ { \
+ goto unaligned; \
+ } \
+ } \
+ while (FALSE)
+
switch (pixels * px_size)
{
case 1:
+ CHECK_ALIGNMENT (guchar);
for (row = offsety;
row < tile_height && y < height;
row++, y++)
@@ -506,6 +532,7 @@ with multi-threading - and should be added back later.
}
break;
case 2:
+ CHECK_ALIGNMENT (uint16_t);
for (row = offsety;
row < tile_height && y < height;
row++, y++)
@@ -521,6 +548,7 @@ with multi-threading - and should be added back later.
}
break;
case 3:
+ CHECK_ALIGNMENT (guchar);
for (row = offsety;
row < tile_height && y < height;
row++, y++)
@@ -537,6 +565,7 @@ with multi-threading - and should be added back later.
}
break;
case 4:
+ CHECK_ALIGNMENT (uint32_t);
for (row = offsety;
row < tile_height && y < height;
row++, y++)
@@ -552,6 +581,7 @@ with multi-threading - and should be added back later.
}
break;
case 8:
+ CHECK_ALIGNMENT (uint64_t);
for (row = offsety;
row < tile_height && y < height;
row++, y++)
@@ -567,6 +597,7 @@ with multi-threading - and should be added back later.
}
break;
case 12:
+ CHECK_ALIGNMENT (uint32_t);
for (row = offsety;
row < tile_height && y < height;
row++, y++)
@@ -586,6 +617,7 @@ with multi-threading - and should be added back later.
}
break;
case 16:
+ CHECK_ALIGNMENT (uint64_t);
for (row = offsety;
row < tile_height && y < height;
row++, y++)
@@ -603,6 +635,7 @@ with multi-threading - and should be added back later.
}
break;
case 24:
+ CHECK_ALIGNMENT (uint64_t);
for (row = offsety;
row < tile_height && y < height;
row++, y++)
@@ -622,6 +655,7 @@ with multi-threading - and should be added back later.
}
break;
case 32:
+ CHECK_ALIGNMENT (uint64_t);
for (row = offsety;
row < tile_height && y < height;
row++, y++)
@@ -643,6 +677,7 @@ with multi-threading - and should be added back later.
}
break;
case 40:
+ CHECK_ALIGNMENT (uint64_t);
for (row = offsety;
row < tile_height && y < height;
row++, y++)
@@ -666,6 +701,7 @@ with multi-threading - and should be added back later.
}
break;
case 48:
+ CHECK_ALIGNMENT (uint64_t);
for (row = offsety;
row < tile_height && y < height;
row++, y++)
@@ -691,6 +727,7 @@ with multi-threading - and should be added back later.
}
break;
case 56:
+ CHECK_ALIGNMENT (uint64_t);
for (row = offsety;
row < tile_height && y < height;
row++, y++)
@@ -718,6 +755,7 @@ with multi-threading - and should be added back later.
}
break;
case 64:
+ CHECK_ALIGNMENT (uint64_t);
for (row = offsety;
row < tile_height && y < height;
row++, y++)
@@ -747,6 +785,7 @@ with multi-threading - and should be added back later.
}
break;
default:
+ unaligned:
for (row = offsety;
row < tile_height && y < height;
row++, y++)
@@ -762,6 +801,9 @@ with multi-threading - and should be added back later.
bp += buf_stride;
}
}
+
+ #undef CHECK_ALIGNMENT
+ #undef CHECK_ALIGNMENT_ALIGNOF
}
gegl_tile_unlock (tile);
@@ -940,9 +982,34 @@ gegl_buffer_iterate_read_simple (GeglBuffer *buffer,
}
else
{
+ #ifdef __GNUC__
+ #define CHECK_ALIGNMENT_ALIGNOF __alignof__
+ #else
+ #define CHECK_ALIGNMENT_ALIGNOF(type) \
+ (G_STRUCT_OFFSET (struct alignof_helper, b))
+ #endif
+ #define CHECK_ALIGNMENT(type) \
+ do \
+ { \
+ struct alignof_helper { char a; type b; }; \
+ /* verify 'alignof (type)' is a power of 2 */ \
+ G_STATIC_ASSERT (! (CHECK_ALIGNMENT_ALIGNOF (type) & \
+ (CHECK_ALIGNMENT_ALIGNOF (type) - 1)));\
+ if (((uintptr_t) tp | \
+ (uintptr_t) bp | \
+ tile_stride | \
+ buf_stride) & \
+ (CHECK_ALIGNMENT_ALIGNOF (type) - 1)) \
+ { \
+ goto unaligned; \
+ } \
+ } \
+ while (FALSE)
+
switch (pixels * px_size)
{
case 1:
+ CHECK_ALIGNMENT (guchar);
for (row = offsety; row < tile_height && y < height;
row++, y++)
{
@@ -952,6 +1019,7 @@ gegl_buffer_iterate_read_simple (GeglBuffer *buffer,
}
break;
case 2:
+ CHECK_ALIGNMENT (uint16_t);
for (row = offsety; row < tile_height && y < height;
row++, y++)
{
@@ -961,6 +1029,7 @@ gegl_buffer_iterate_read_simple (GeglBuffer *buffer,
}
break;
case 3:
+ CHECK_ALIGNMENT (guchar);
for (row = offsety; row < tile_height && y < height;
row++, y++)
{
@@ -972,6 +1041,7 @@ gegl_buffer_iterate_read_simple (GeglBuffer *buffer,
}
break;
case 4:
+ CHECK_ALIGNMENT (uint32_t);
for (row = offsety; row < tile_height && y < height;
row++, y++)
{
@@ -981,6 +1051,7 @@ gegl_buffer_iterate_read_simple (GeglBuffer *buffer,
}
break;
case 6:
+ CHECK_ALIGNMENT (uint16_t);
for (row = offsety; row < tile_height && y < height;
row++, y++)
{
@@ -992,6 +1063,7 @@ gegl_buffer_iterate_read_simple (GeglBuffer *buffer,
}
break;
case 8:
+ CHECK_ALIGNMENT (uint64_t);
for (row = offsety; row < tile_height && y < height;
row++, y++)
{
@@ -1001,6 +1073,7 @@ gegl_buffer_iterate_read_simple (GeglBuffer *buffer,
}
break;
case 12:
+ CHECK_ALIGNMENT (uint32_t);
for (row = offsety; row < tile_height && y < height;
row++, y++)
{
@@ -1012,6 +1085,7 @@ gegl_buffer_iterate_read_simple (GeglBuffer *buffer,
}
break;
case 16:
+ CHECK_ALIGNMENT (uint64_t);
for (row = offsety; row < tile_height && y < height;
row++, y++)
{
@@ -1022,6 +1096,7 @@ gegl_buffer_iterate_read_simple (GeglBuffer *buffer,
}
break;
case 24:
+ CHECK_ALIGNMENT (uint64_t);
for (row = offsety; row < tile_height && y < height;
row++, y++)
{
@@ -1033,6 +1108,7 @@ gegl_buffer_iterate_read_simple (GeglBuffer *buffer,
}
break;
case 32:
+ CHECK_ALIGNMENT (uint64_t);
for (row = offsety; row < tile_height && y < height;
row++, y++)
{
@@ -1045,6 +1121,7 @@ gegl_buffer_iterate_read_simple (GeglBuffer *buffer,
}
break;
case 40:
+ CHECK_ALIGNMENT (uint64_t);
for (row = offsety; row < tile_height && y < height;
row++, y++)
{
@@ -1058,6 +1135,7 @@ gegl_buffer_iterate_read_simple (GeglBuffer *buffer,
}
break;
case 48:
+ CHECK_ALIGNMENT (uint64_t);
for (row = offsety; row < tile_height && y < height;
row++, y++)
{
@@ -1072,6 +1150,7 @@ gegl_buffer_iterate_read_simple (GeglBuffer *buffer,
}
break;
case 56:
+ CHECK_ALIGNMENT (uint64_t);
for (row = offsety; row < tile_height && y < height;
row++, y++)
{
@@ -1087,6 +1166,7 @@ gegl_buffer_iterate_read_simple (GeglBuffer *buffer,
}
break;
case 64:
+ CHECK_ALIGNMENT (uint64_t);
for (row = offsety; row < tile_height && y < height;
row++, y++)
{
@@ -1104,6 +1184,7 @@ gegl_buffer_iterate_read_simple (GeglBuffer *buffer,
break;
default:
+ unaligned:
for (row = offsety;
row < tile_height && y < height;
row++, y++)
@@ -1113,6 +1194,9 @@ gegl_buffer_iterate_read_simple (GeglBuffer *buffer,
bp += buf_stride;
}
}
+
+ #undef CHECK_ALIGNMENT
+ #undef CHECK_ALIGNMENT_ALIGNOF
}
gegl_tile_unref (tile);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]