From fbe2788623ba7a1b21cbc2ab4b00b46ae98e46d2 Mon Sep 17 00:00:00 2001 From: s1lentq Date: Fri, 2 Feb 2024 04:43:08 +0700 Subject: [PATCH] Add safe check for weapon natives (make sure it's a CBasePlayerWeapon instance) --- reapi/src/natives/natives_helper.h | 1 + reapi/src/natives/natives_misc.cpp | 50 ++++++++++++++++++++++++------ 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/reapi/src/natives/natives_helper.h b/reapi/src/natives/natives_helper.h index 6ec6b5e..f6c664e 100644 --- a/reapi/src/natives/natives_helper.h +++ b/reapi/src/natives/natives_helper.h @@ -6,6 +6,7 @@ #define CHECK_ISENTITY(x) if (unlikely(params[x] < 0 || params[x] > gpGlobals->maxEntities)) { AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid entity index %i [%s]", __FUNCTION__, params[x], #x); return FALSE; } #define CHECK_GAMERULES() if (unlikely(!g_pGameRules)) { AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: gamerules not initialized", __FUNCTION__); return FALSE; } #define CHECK_CONNECTED(x, y) if (unlikely(x == nullptr || x->has_disconnected)) { AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: player %i is not connected", __FUNCTION__, params[y]); return FALSE; } +#define CHECK_INSTANCE_OF(x, y) if (unlikely(dynamic_cast((x::BaseClass *)y) == nullptr)) { AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid entity %d ('%s'), is not an instance of the base class '%s'", __FUNCTION__, indexOfEdict(y->pev), STRING(y->pev->classname), #x); return FALSE; } class CAmxArg { diff --git a/reapi/src/natives/natives_misc.cpp b/reapi/src/natives/natives_misc.cpp index 5a01e14..609695c 100644 --- a/reapi/src/natives/natives_misc.cpp +++ b/reapi/src/natives/natives_misc.cpp @@ -1675,8 +1675,15 @@ cell AMX_NATIVE_CALL rg_instant_reload_weapons(AMX *amx, cell *params) if (params[arg_weapon] != 0) { pWeapon = getPrivate(params[arg_weapon]); - if (!pWeapon || !pWeapon->IsWeapon()) { - AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: Invalid entity weapon", __FUNCTION__); + if (unlikely(pWeapon == nullptr)) { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized entity", __FUNCTION__); + return FALSE; + } + + CHECK_INSTANCE_OF(CBasePlayerWeapon, pWeapon); + + if (!pWeapon->IsWeapon()) { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: #%d entity is not a weapon.", __FUNCTION__, indexOfEdict(pWeapon->pev)); return FALSE; } } @@ -1867,9 +1874,16 @@ cell AMX_NATIVE_CALL rg_switch_weapon(AMX *amx, cell *params) CBasePlayer *pPlayer = UTIL_PlayerByIndex(params[arg_index]); CHECK_CONNECTED(pPlayer, arg_index); - auto pWeapon = getPrivate(params[arg_weapon]); - if (pWeapon == nullptr || !pWeapon->IsWeapon()) { - AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: Invalid entity weapon", __FUNCTION__); + CBasePlayerWeapon *pWeapon = getPrivate(params[arg_weapon]); + if (unlikely(pWeapon == nullptr)) { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized entity", __FUNCTION__); + return FALSE; + } + + CHECK_INSTANCE_OF(CBasePlayerWeapon, pWeapon); + + if (!pWeapon->IsWeapon()) { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: #%d entity is not a weapon.", __FUNCTION__, indexOfEdict(pWeapon->pev)); return FALSE; } @@ -2142,6 +2156,8 @@ cell AMX_NATIVE_CALL rg_set_iteminfo(AMX *amx, cell *params) return FALSE; } + CHECK_INSTANCE_OF(CBasePlayerWeapon, pWeapon); + if (!pWeapon->IsWeapon()) { AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: #%d entity is not a weapon.", __FUNCTION__, indexOfEdict(pWeapon->pev)); return FALSE; @@ -2205,6 +2221,8 @@ cell AMX_NATIVE_CALL rg_get_iteminfo(AMX *amx, cell *params) return FALSE; } + CHECK_INSTANCE_OF(CBasePlayerWeapon, pWeapon); + if (!pWeapon->IsWeapon()) { AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: #%d entity is not a weapon.", __FUNCTION__, indexOfEdict(pWeapon->pev)); return FALSE; @@ -2834,6 +2852,8 @@ cell AMX_NATIVE_CALL rg_weapon_deploy(AMX* amx, cell* params) return FALSE; } + CHECK_INSTANCE_OF(CBasePlayerWeapon, pWeapon); + if (!pWeapon->IsWeapon()) { AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: #%d entity is not a weapon.", __FUNCTION__, indexOfEdict(pWeapon->pev)); @@ -2898,6 +2918,8 @@ cell AMX_NATIVE_CALL rg_weapon_reload(AMX* amx, cell* params) return FALSE; } + CHECK_INSTANCE_OF(CBasePlayerWeapon, pWeapon); + if (!pWeapon->IsWeapon()) { AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: #%d entity is not a weapon.", __FUNCTION__, indexOfEdict(pWeapon->pev)); @@ -2968,6 +2990,8 @@ cell AMX_NATIVE_CALL rg_weapon_shotgun_reload(AMX* amx, cell* params) return FALSE; } + CHECK_INSTANCE_OF(CBasePlayerWeapon, pWeapon); + if (!pWeapon->IsWeapon()) { AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: #%d entity is not a weapon.", __FUNCTION__, indexOfEdict(pWeapon->pev)); @@ -3032,6 +3056,8 @@ cell AMX_NATIVE_CALL rg_weapon_send_animation(AMX* amx, cell* params) return FALSE; } + CHECK_INSTANCE_OF(CBasePlayerWeapon, pWeapon); + if (!pWeapon->IsWeapon()) { AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: #%d entity is not a weapon.", __FUNCTION__, indexOfEdict(pWeapon->pev)); @@ -3097,6 +3123,8 @@ cell AMX_NATIVE_CALL rg_weapon_kickback(AMX* amx, cell* params) return FALSE; } + CHECK_INSTANCE_OF(CBasePlayerWeapon, pWeapon); + if (!pWeapon->IsWeapon()) { AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: #%d entity is not a weapon.", __FUNCTION__, indexOfEdict(pWeapon->pev)); @@ -3151,11 +3179,6 @@ cell AMX_NATIVE_CALL rg_switch_best_weapon(AMX* amx, cell* params) AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized entity", __FUNCTION__); return FALSE; } - - if (!pWeapon->IsWeapon()) { - AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: #%d entity is not a weapon.", __FUNCTION__, indexOfEdict(pWeapon->pev)); - return FALSE; - } } else { @@ -3167,6 +3190,13 @@ cell AMX_NATIVE_CALL rg_switch_best_weapon(AMX* amx, cell* params) } } + CHECK_INSTANCE_OF(CBasePlayerWeapon, pWeapon); + + if (!pWeapon->IsWeapon()) { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: #%d entity is not a weapon.", __FUNCTION__, indexOfEdict(pWeapon->pev)); + return FALSE; + } + return CSGameRules()->GetNextBestWeapon(pPlayer, pWeapon); }