From: Martin Storsjö martin@martin.st
While armv7 generally tolerates unaligned loads/stores in most cases, the compiler is free to use the ldrd/strd instructions, for loading/storing two consecutive 32 bit registers, and this requires the destination to be aligned to a 4 byte boundary.
When packing a number of variable length structures, make sure that each actual struct gets aligned at the right address boundary.
This fixes crashes in DllMain of wineps.drv, when built for armv7, since 351e58dc2d0aafe19294cbeaed9cd30ae965d591.
Signed-off-by: Martin Storsjö martin@martin.st --- dlls/wineps.drv/init.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/dlls/wineps.drv/init.c b/dlls/wineps.drv/init.c index 8537ba287d1..eabdc5546ae 100644 --- a/dlls/wineps.drv/init.c +++ b/dlls/wineps.drv/init.c @@ -36,6 +36,9 @@
WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
+#define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align))&~(_Align)) +#define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align) + static const PSDRV_DEVMODE DefaultDevmode = { { /* dmPublic */ @@ -155,14 +158,16 @@ static BOOL convert_afm_to_ntf(void) for(afmle = family->afmlist; afmle; afmle = afmle->next) count++; } - size = sizeof(*header) + sizeof(*list) * count * 2; + size = ALIGNED_LENGTH(sizeof(*header), TYPE_ALIGNMENT(struct list_entry) - 1) + + sizeof(*list) * count * 2; + ALIGN_LENGTH(size, TYPE_ALIGNMENT(struct glyph_set) - 1); data = calloc(size, 1);
if (!data) return FALSE; header = (void *)data; header->glyph_set_count = count; - header->glyph_set_off = sizeof(*header); + header->glyph_set_off = ALIGNED_LENGTH(sizeof(*header), TYPE_ALIGNMENT(struct list_entry) - 1); header->font_mtx_count = count; header->font_mtx_off = header->glyph_set_off + sizeof(*list) * count;
@@ -180,6 +185,7 @@ static BOOL convert_afm_to_ntf(void) sizeof(short) * afmle->afm->NumofMetrics; list->off = off; size += list->size; + ALIGN_LENGTH(size, TYPE_ALIGNMENT(struct font_mtx) - 1); new_data = realloc(data, size); if (!new_data) { @@ -209,11 +215,12 @@ static BOOL convert_afm_to_ntf(void) (wcslen(afmle->afm->FamilyName) + 1) * sizeof(WCHAR); list = (void *)(data + header->font_mtx_off + sizeof(*list) * count); list->name_off = off + sizeof(*font_mtx); - list->size = sizeof(*font_mtx) + strlen(afmle->afm->FontName) + 1 + - strlen(glyph_set_name) + 1 + metrics_size + + list->size = ALIGNED_LENGTH(sizeof(*font_mtx) + strlen(afmle->afm->FontName) + 1 + + strlen(glyph_set_name) + 1, TYPE_ALIGNMENT(IFIMETRICS) - 1) + metrics_size + (afmle->afm->IsFixedPitch ? 0 : sizeof(*width_range) * afmle->afm->NumofMetrics); list->off = off; size += list->size; + ALIGN_LENGTH(size, TYPE_ALIGNMENT(struct glyph_set) - 1); new_data = realloc(data, size); if (!new_data) { @@ -229,7 +236,8 @@ static BOOL convert_afm_to_ntf(void) font_mtx->name_off = sizeof(*font_mtx); font_mtx->glyph_set_name_off = font_mtx->name_off + strlen(afmle->afm->FontName) + 1; font_mtx->glyph_count = afmle->afm->NumofMetrics; - font_mtx->metrics_off = font_mtx->glyph_set_name_off + strlen(glyph_set_name) + 1; + font_mtx->metrics_off = ALIGNED_LENGTH(font_mtx->glyph_set_name_off + strlen(glyph_set_name) + 1, + TYPE_ALIGNMENT(IFIMETRICS) - 1); font_mtx->width_count = afmle->afm->IsFixedPitch ? 0 : afmle->afm->NumofMetrics; font_mtx->width_off = font_mtx->metrics_off + metrics_size; font_mtx->def_width = afmle->afm->Metrics[0].WX;