From f0a957db22c90c82817674c1cf3c53976e44fa87 Mon Sep 17 00:00:00 2001 From: bones_was_here Date: Mon, 6 May 2024 11:15:40 +1000 Subject: [PATCH] sprites: fix misaligned memory access while loading (v2) This reverts commit 0d5f8f0edd073d7ff233bde3995b529c0fcb67ff, that approach didn't solve it for the other code path (used in mod "quake15") so we need to memcpy each struct. Signed-off-by: bones_was_here --- model_sprite.c | 64 +++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/model_sprite.c b/model_sprite.c index 5b2e36d7..7e96f676 100644 --- a/model_sprite.c +++ b/model_sprite.c @@ -90,16 +90,16 @@ extern cvar_t gl_texturecompression_sprites; static void Mod_Sprite_SharedSetup(const unsigned char *datapointer, int version, const unsigned int *palette, qbool additive) { - int i, j, groupframes, realframes, x, y, origin[2], width, height; - qbool fullbright; - dspriteframetype_t *pinframetype; - dspriteframe_t *pinframe; - dspritegroup_t *pingroup; - dspriteinterval_t *pinintervals; - skinframe_t *skinframe; - float modelradius, interval; - char name[MAX_QPATH], fogname[MAX_QPATH]; - const void *startframes; + int i, j, groupframes, realframes, x, y, origin[2], width, height; + qbool fullbright; + dspriteframetype_t pinframetype; + dspriteframe_t pinframe; + dspritegroup_t pingroup; + dspriteinterval_t pinintervals; + skinframe_t *skinframe; + float modelradius, interval; + char name[MAX_QPATH], fogname[MAX_QPATH]; + const void *startframes; int texflags = (r_mipsprites.integer ? TEXF_MIPMAP : 0) | ((gl_texturecompression.integer && gl_texturecompression_sprites.integer) ? TEXF_COMPRESS : 0) | TEXF_ISSPRITE | TEXF_PICMIP | TEXF_ALPHA | TEXF_CLAMP; modelradius = 0; @@ -114,33 +114,34 @@ static void Mod_Sprite_SharedSetup(const unsigned char *datapointer, int version // // load the frames +// bones_was_here: memcpy() used here to prevent misaligned access with struct-based parsing // startframes = datapointer; realframes = 0; for (i = 0;i < loadmodel->numframes;i++) { - pinframetype = (dspriteframetype_t *)datapointer; + memcpy(&pinframetype, datapointer, sizeof(dspriteframetype_t)); datapointer += sizeof(dspriteframetype_t); - if (LittleLong (pinframetype->type) == SPR_SINGLE) + if (LittleLong (pinframetype.type) == SPR_SINGLE) groupframes = 1; else { - pingroup = (dspritegroup_t *)datapointer; + memcpy(&pingroup, datapointer, sizeof(dspritegroup_t)); datapointer += sizeof(dspritegroup_t); - groupframes = LittleLong(pingroup->numframes); + groupframes = LittleLong(pingroup.numframes); datapointer += sizeof(dspriteinterval_t) * groupframes; } for (j = 0;j < groupframes;j++) { - pinframe = (dspriteframe_t *)datapointer; + memcpy(&pinframe, datapointer, sizeof(dspriteframe_t)); if (version == SPRITE32_VERSION) - datapointer += sizeof(dspriteframe_t) + LittleLong(pinframe->width) * LittleLong(pinframe->height) * 4; + datapointer += sizeof(dspriteframe_t) + LittleLong(pinframe.width) * LittleLong(pinframe.height) * 4; else //if (version == SPRITE_VERSION || version == SPRITEHL_VERSION) - datapointer += sizeof(dspriteframe_t) + LittleLong(pinframe->width) * LittleLong(pinframe->height); + datapointer += sizeof(dspriteframe_t) + LittleLong(pinframe.width) * LittleLong(pinframe.height); } realframes += groupframes; } @@ -155,25 +156,25 @@ static void Mod_Sprite_SharedSetup(const unsigned char *datapointer, int version realframes = 0; for (i = 0;i < loadmodel->numframes;i++) { - pinframetype = (dspriteframetype_t *)datapointer; + memcpy(&pinframetype, datapointer, sizeof(dspriteframetype_t)); datapointer += sizeof(dspriteframetype_t); - if (LittleLong (pinframetype->type) == SPR_SINGLE) + if (LittleLong (pinframetype.type) == SPR_SINGLE) { groupframes = 1; interval = 0.1f; } else { - pingroup = (dspritegroup_t *)datapointer; + memcpy(&pingroup, datapointer, sizeof(dspritegroup_t)); datapointer += sizeof(dspritegroup_t); - groupframes = LittleLong(pingroup->numframes); + groupframes = LittleLong(pingroup.numframes); - pinintervals = (dspriteinterval_t *)datapointer; + memcpy(&pinintervals, datapointer, sizeof(dspriteinterval_t)); datapointer += sizeof(dspriteinterval_t) * groupframes; - interval = LittleFloat(pinintervals[0].interval); + interval = LittleFloat(pinintervals.interval); if (interval < 0.01f) Host_Error("Mod_Sprite_SharedSetup: invalid interval"); } @@ -186,13 +187,13 @@ static void Mod_Sprite_SharedSetup(const unsigned char *datapointer, int version for (j = 0;j < groupframes;j++) { - pinframe = (dspriteframe_t *)datapointer; + memcpy(&pinframe, datapointer, sizeof(dspriteframe_t)); datapointer += sizeof(dspriteframe_t); - origin[0] = LittleLong (pinframe->origin[0]); - origin[1] = LittleLong (pinframe->origin[1]); - width = LittleLong (pinframe->width); - height = LittleLong (pinframe->height); + origin[0] = LittleLong (pinframe.origin[0]); + origin[1] = LittleLong (pinframe.origin[1]); + width = LittleLong (pinframe.width); + height = LittleLong (pinframe.height); loadmodel->sprite.sprdata_frames[realframes].left = origin[0]; loadmodel->sprite.sprdata_frames[realframes].right = origin[0] + width; @@ -298,7 +299,6 @@ void Mod_IDSP_Load(model_t *mod, void *buffer, void *bufferend) unsigned char palette[256][4]; const unsigned char *in; dspritehl_t *pinhlsprite; - unsigned char *aligneddata; pinhlsprite = (dspritehl_t *)datapointer; datapointer += sizeof(dspritehl_t); @@ -362,11 +362,7 @@ void Mod_IDSP_Load(model_t *mod, void *buffer, void *bufferend) return; } - // the above datapointer arithmetic causes misaligned access - aligneddata = (unsigned char *)Mem_Alloc(tempmempool, (unsigned char *)bufferend - datapointer); - memcpy(aligneddata, datapointer, (unsigned char *)bufferend - datapointer); - Mod_Sprite_SharedSetup(aligneddata, LittleLong (pinhlsprite->version), (unsigned int *)(&palette[0][0]), rendermode == SPRHL_ADDITIVE); - Mem_Free(aligneddata); + Mod_Sprite_SharedSetup(datapointer, LittleLong (pinhlsprite->version), (unsigned int *)(&palette[0][0]), rendermode == SPRHL_ADDITIVE); } else Host_Error("Mod_IDSP_Load: %s has wrong version number (%i). Only %i (quake), %i (HalfLife), and %i (sprite32) supported", -- 2.39.2