From d85fb7487e5c71760a976542ec87577ee1c93deb Mon Sep 17 00:00:00 2001 From: NoiseByNorthwest Date: Sat, 22 Jun 2024 01:33:18 +0200 Subject: [PATCH] Fix secondary weapon models registering Several people have noticed a curious regression which cause some secondary weapon models (such as machinegun's barrel) to not be rendered. For instance: - https://github.com/OpenArena/gamecode/issues/316 - https://github.com/OpenArena/engine/issues/85 - https://forum.manjaro.org/t/openarena-lightning-gun-beam-not-visible-with-glibc-2-37-x86-64-bug/135312 And some people have hypothesized that this could have something to do with a recent change in glibc. I'm also facing this issue since an upgrade from ubuntu 22.04 to 24.04 and I've found its cause, here is the patch. As you can see the logic to add a suffix to the primary weapon model was previously based on a call to COM_StripExtension() with the same pointer for in & out. However, this function passes in & out to Q_strncpyz() which itself relies on strncpy() which does not specify the expected behavior in case of aliasing/overlapping of src & dst. So it was relying on an unspecified behavior, prone to change at any time and without any communication. This patch passes the build step but I've tested it in-game with the legacy project https://github.com/OpenArena/legacy and a back-ported version of it. --- code/cgame/cg_weapons.c | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/code/cgame/cg_weapons.c b/code/cgame/cg_weapons.c index fedadae6..ed21b6b4 100644 --- a/code/cgame/cg_weapons.c +++ b/code/cgame/cg_weapons.c @@ -855,8 +855,7 @@ void CG_RegisterWeapon( int weaponNum ) weaponInfo->ammoModel = trap_R_RegisterModel( ammo->world_model[0] ); } - Q_strncpyz( path, item->world_model[0], MAX_QPATH ); - COM_StripExtension(path, path, sizeof(path)); + COM_StripExtension(item->world_model[0], path, sizeof(path)); Q_strcat( path, sizeof(path), "_flash.md3" ); weaponInfo->flashModel = trap_R_RegisterModel( path ); @@ -866,39 +865,32 @@ void CG_RegisterWeapon( int weaponNum ) // leilei - additional flash styles - Q_strncpyz( path, item->world_model[0], MAX_QPATH ); - COM_StripExtension(path, path, sizeof(path)); + COM_StripExtension(item->world_model[0], path, sizeof(path)); Q_strcat( path, sizeof(path), "_flash1.md3" ); weaponInfo->flashModel_type1 = trap_R_RegisterModel( path ); - Q_strncpyz( path, item->world_model[0], MAX_QPATH ); - COM_StripExtension(path, path, sizeof(path)); + COM_StripExtension(item->world_model[0], path, sizeof(path)); Q_strcat( path, sizeof(path), "_flash2.md3" ); weaponInfo->flashModel_type2 = trap_R_RegisterModel( path ); - Q_strncpyz( path, item->world_model[0], MAX_QPATH ); - COM_StripExtension(path, path, sizeof(path)); + COM_StripExtension(item->world_model[0], path, sizeof(path)); Q_strcat( path, sizeof(path), "_flash2a.md3" ); weaponInfo->flashModel_type2a = trap_R_RegisterModel( path ); - Q_strncpyz( path, item->world_model[0], MAX_QPATH ); - COM_StripExtension(path, path, sizeof(path)); + COM_StripExtension(item->world_model[0], path, sizeof(path)); Q_strcat( path, sizeof(path), "_flash3.md3" ); weaponInfo->flashModel_type3 = trap_R_RegisterModel( path ); - Q_strncpyz( path, item->world_model[0], MAX_QPATH ); - COM_StripExtension(path, path, sizeof(path)); + COM_StripExtension(item->world_model[0], path, sizeof(path)); Q_strcat( path, sizeof(path), "_flash4.md3" ); weaponInfo->flashModel_type4 = trap_R_RegisterModel( path ); - Q_strncpyz( path, item->world_model[0], MAX_QPATH ); - COM_StripExtension(path, path, sizeof(path)); + COM_StripExtension(item->world_model[0], path, sizeof(path)); Q_strcat( path, sizeof(path), "_flash5.md3" ); weaponInfo->flashModel_type5 = trap_R_RegisterModel( path ); - Q_strncpyz( path, item->world_model[0], MAX_QPATH ); - COM_StripExtension(path, path, sizeof(path)); + COM_StripExtension(item->world_model[0], path, sizeof(path)); Q_strcat( path, sizeof(path), "_flash5a.md3" ); weaponInfo->flashModel_type5a = trap_R_RegisterModel( path ); @@ -917,13 +909,11 @@ void CG_RegisterWeapon( int weaponNum ) if (!weaponInfo->flashModel_type5) weaponInfo->flashModel_type5 = trap_R_RegisterModel( "models/muzzle/flash5.md3" ); if (!weaponInfo->flashModel_type5a) weaponInfo->flashModel_type5a = trap_R_RegisterModel( "models/muzzle/flash5a.md3" ); - Q_strncpyz( path, item->world_model[0], MAX_QPATH ); - COM_StripExtension(path, path, sizeof(path)); + COM_StripExtension(item->world_model[0], path, sizeof(path)); Q_strcat( path, sizeof(path), "_barrel.md3" ); weaponInfo->barrelModel = trap_R_RegisterModel( path ); - Q_strncpyz( path, item->world_model[0], MAX_QPATH ); - COM_StripExtension(path, path, sizeof(path)); + COM_StripExtension(item->world_model[0], path, sizeof(path)); Q_strcat( path, sizeof(path), "_hand.md3" ); weaponInfo->handsModel = trap_R_RegisterModel( path );