1
0
mirror of https://github.com/Mauler125/r5sdk.git synced 2025-02-09 19:15:03 +01:00

Fix server code crasher in 'FireWeaponBolt'

The function 'FireWeaponBolt' calls 'CreateWeaponBolt' to create a bolt entity, but it can return NULL. 'FireWeaponBolt' does NOT check for NULL and derefs the pointer regardless. This rarely happens though; in all cases, it was caused by a defect in scripts. Code has been hooked to throw an engine error instead of crashing.
This commit is contained in:
Kawe Mazidjatari 2023-05-31 23:58:10 +02:00
parent 177cf2ca55
commit 8e379457bf
4 changed files with 84 additions and 0 deletions

@ -105,6 +105,7 @@
#include "vscript/languages/squirrel_re/include/sqstdaux.h"
#include "vscript/languages/squirrel_re/vsquirrel.h"
#include "vscript/vscript.h"
#include "game/shared/r1/weapon_bolt.h"
#include "game/shared/util_shared.h"
#include "game/shared/usercmd.h"
#include "game/shared/animation.h"
@ -536,6 +537,8 @@ void DetourRegister() // Register detour classes to be searched and hooked.
REGISTER(VAnimation);
REGISTER(VUtil_Shared);
REGISTER(V_Weapon_Bolt);
#ifndef CLIENT_DLL
// Game/server

@ -26,6 +26,11 @@ add_sources( SOURCE_GROUP "Shared"
"shared/vscript_shared.h"
)
add_sources( SOURCE_GROUP "Shared/Weapon"
"shared/r1/weapon_bolt.cpp"
"shared/r1/weapon_bolt.h"
)
add_sources( SOURCE_GROUP "Server"
"server/ai_network.cpp"
"server/ai_network.h"

@ -0,0 +1,31 @@
#include "weapon_bolt.h"
#include "game/shared/util_shared.h"
//-----------------------------------------------------------------------------
// Purpose: creates a weapon bolt
//-----------------------------------------------------------------------------
CBaseEntity* CreateWeaponBolt(Vector3D* origin, Vector3D* end, __int64 unused, float scale, CPlayer* player,
int a6, int modelIndex, int a8, unsigned __int8 a9, unsigned int a10, CBaseEntity* weapon)
{
CBaseEntity* weaponBolt = v_CreateWeaponBolt(origin, end, unused, scale, player, a6, modelIndex, a8, a9, a10, weapon);
if (!weaponBolt)
{
// Code does NOT check for null, and performing inline assembly is kind of a waste.
// This only happens when 'EntityFactoryDictionary' fails, which only happens when
// there are no edict slots available anymore (usually a bug in scripts).
Error(eDLL_T::SERVER, EXIT_FAILURE, "Unable to create bolt for %s", UTIL_GetEntityScriptInfo(player));
}
return weaponBolt;
}
//-----------------------------------------------------------------------------
void V_Weapon_Bolt::Attach() const
{
DetourAttach(&v_CreateWeaponBolt, &CreateWeaponBolt);
}
void V_Weapon_Bolt::Detach() const
{
DetourDetach(&v_CreateWeaponBolt, &CreateWeaponBolt);
}

@ -0,0 +1,45 @@
#ifndef GAME_WEAPON_BOLT_H
#define GAME_WEAPON_BOLT_H
#ifndef CLIENT_DLL
#include <game/server/baseentity.h>
#include <game/server/player.h>
#else
#include <game/client/c_baseentity.h>
#include <game/client/c_baseplayer.h>
#endif
CBaseEntity* CreateWeaponBolt(Vector3D* origin, Vector3D* end, __int64 unused, float scale, CPlayer* unkEnt,
int a6, int modelindex, int a8, unsigned __int8 a9, unsigned int a10, CBaseEntity* weaponEnt);
inline CMemory p_CreateWeaponBolt;
inline auto v_CreateWeaponBolt = p_CreateWeaponBolt.RCast<CBaseEntity*(*)(
Vector3D* origin, Vector3D* end, __int64 unused, float scale, CPlayer* player,
int a6, int modelindex, int a8, unsigned __int8 a9, unsigned int a10, CBaseEntity* weapon)>();
///////////////////////////////////////////////////////////////////////////////
class V_Weapon_Bolt : public IDetour
{
virtual void GetAdr(void) const
{
LogFunAdr("CreateWeaponBolt", p_CreateWeaponBolt.GetPtr());
}
virtual void GetFun(void) const { }
virtual void GetVar(void) const
{
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
p_CreateWeaponBolt = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 56 57 41 54 41 55 41 56 48 81 EC ?? ?? ?? ??");
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
p_CreateWeaponBolt = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 41 56 41 57 48 83 EC 70");
#endif
v_CreateWeaponBolt = p_CreateWeaponBolt.RCast<CBaseEntity* (*)(
Vector3D*, Vector3D*, __int64, float, CPlayer*,
int, int, int, unsigned __int8, unsigned int, CBaseEntity*)>();
}
virtual void GetCon(void) const { }
virtual void Attach(void) const;
virtual void Detach(void) const;
};
///////////////////////////////////////////////////////////////////////////////
#endif // GAME_WEAPON_BOLT_H