From e8058912b86d0a95ddfee738b86dcfcfb2882722 Mon Sep 17 00:00:00 2001 From: Kyle Sanderson Date: Tue, 28 Aug 2012 16:20:15 -0400 Subject: [PATCH] Fixed crash in EntProp natives (bug 5297, r=psychonic). --- core/HalfLife2.cpp | 35 ++++++++++++++++++++ core/HalfLife2.h | 2 ++ core/smn_entities.cpp | 75 ++++++------------------------------------- public/IGameHelpers.h | 18 ++++++++++- 4 files changed, 63 insertions(+), 67 deletions(-) diff --git a/core/HalfLife2.cpp b/core/HalfLife2.cpp index 95068a89..f03d9893 100644 --- a/core/HalfLife2.cpp +++ b/core/HalfLife2.cpp @@ -1009,3 +1009,38 @@ int CHalfLife2::GetSendPropOffset(SendProp *prop) return prop->GetOffset(); } +const char *CHalfLife2::GetEntityClassname(edict_t * pEdict) +{ + if (pEdict == NULL || pEdict->IsFree()) + { + return NULL; + } + + IServerUnknown *pUnk = pEdict->GetUnknown(); + if (pUnk == NULL) + { + return NULL; + } + + CBaseEntity * pEntity = pUnk->GetBaseEntity(); + + if (pEntity == NULL) + { + return NULL; + } + + return GetEntityClassname(pEntity); +} + +const char *CHalfLife2::GetEntityClassname(CBaseEntity *pEntity) +{ + static int offset = -1; + if (offset == -1) + { + datamap_t *pMap = GetDataMap(pEntity); + typedescription_t *pDesc = FindInDataMap(pMap, "m_iClassname"); + offset = GetTypeDescOffs(pDesc); + } + + return *(const char **)(((unsigned char *)pEntity) + offset); +} diff --git a/core/HalfLife2.h b/core/HalfLife2.h index de39ac3b..46f2654f 100644 --- a/core/HalfLife2.h +++ b/core/HalfLife2.h @@ -146,6 +146,8 @@ public: //IGameHelpers void *GetGlobalEntityList(); int GetSendPropOffset(SendProp *prop); ICommandLine *GetValveCommandLine(); + const char *GetEntityClassname(edict_t *pEdict); + const char *GetEntityClassname(CBaseEntity *pEntity); public: void AddToFakeCliCmdQueue(int client, int userid, const char *cmd); void ProcessFakeCliCmdQueue(); diff --git a/core/smn_entities.cpp b/core/smn_entities.cpp index 2561951c..49ea4632 100644 --- a/core/smn_entities.cpp +++ b/core/smn_entities.cpp @@ -325,7 +325,7 @@ static cell_t GetEdictClassname(IPluginContext *pContext, const cell_t *params) return pContext->ThrowNativeError("Invalid edict (%d - %d)", g_HL2.ReferenceToIndex(params[1]), params[1]); } - const char *cls = pEdict->GetClassName(); + const char *cls = g_HL2.GetEntityClassname(pEdict); if (!cls || cls[0] == '\0') { @@ -961,10 +961,11 @@ static cell_t SetEntDataString(IPluginContext *pContext, const cell_t *params) } \ if ((td = g_HL2.FindInDataMap(pMap, prop)) == NULL) \ { \ + const char *class_name = g_HL2.GetEntityClassname(pEntity); \ return pContext->ThrowNativeError("Property \"%s\" not found (entity %d/%s)", \ prop, \ params[1], \ - class_name); \ + ((class_name) ? class_name : "")); \ } #define CHECK_SET_PROP_DATA_OFFSET() \ @@ -988,10 +989,11 @@ static cell_t SetEntDataString(IPluginContext *pContext, const cell_t *params) } \ if (!g_HL2.FindSendPropInfo(pNet->GetServerClass()->GetName(), prop, &info)) \ { \ + const char *class_name = g_HL2.GetEntityClassname(pEntity); \ return pContext->ThrowNativeError("Property \"%s\" not found (entity %d/%s)", \ prop, \ params[1], \ - class_name); \ + ((class_name) ? class_name : "")); \ } \ \ offset = info.actual_offset; \ @@ -1082,7 +1084,6 @@ static cell_t GetEntPropArraySize(IPluginContext *pContext, const cell_t *params { CBaseEntity *pEntity; char *prop; - const char *class_name; edict_t *pEdict; if (!IndexToAThings(params[1], &pEntity, &pEdict)) @@ -1090,11 +1091,6 @@ static cell_t GetEntPropArraySize(IPluginContext *pContext, const cell_t *params return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]); } - if (!pEdict || (class_name = pEdict->GetClassName()) == NULL) - { - class_name = ""; - } - pContext->LocalToString(params[3], &prop); switch (params[2]) @@ -1119,10 +1115,11 @@ static cell_t GetEntPropArraySize(IPluginContext *pContext, const cell_t *params } if (!g_HL2.FindSendPropInfo(pNet->GetServerClass()->GetName(), prop, &info)) { + const char *class_name = g_HL2.GetEntityClassname(pEntity); return pContext->ThrowNativeError("Property \"%s\" not found (entity %d/%s)", prop, params[1], - class_name); + ((class_name) ? class_name : "")); } if (info.prop->GetType() != DPT_DataTable) @@ -1152,7 +1149,6 @@ static cell_t GetEntProp(IPluginContext *pContext, const cell_t *params) CBaseEntity *pEntity; char *prop; int offset; - const char *class_name; edict_t *pEdict; int bit_count; bool is_unsigned = false; @@ -1168,12 +1164,6 @@ static cell_t GetEntProp(IPluginContext *pContext, const cell_t *params) return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]); } - /* TODO: Find a way to lookup classname without having an edict - Is this a guaranteed prop? */ - if (!pEdict || (class_name = pEdict->GetClassName()) == NULL) - { - class_name = ""; - } - pContext->LocalToString(params[3], &prop); switch (params[2]) @@ -1251,7 +1241,6 @@ static cell_t SetEntProp(IPluginContext *pContext, const cell_t *params) CBaseEntity *pEntity; char *prop; int offset; - const char *class_name; edict_t *pEdict; int bit_count; @@ -1266,11 +1255,6 @@ static cell_t SetEntProp(IPluginContext *pContext, const cell_t *params) return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]); } - if (!pEdict || (class_name = pEdict->GetClassName()) == NULL) - { - class_name = ""; - } - pContext->LocalToString(params[3], &prop); switch (params[2]) @@ -1339,7 +1323,6 @@ static cell_t GetEntPropFloat(IPluginContext *pContext, const cell_t *params) char *prop; int offset; int bit_count; - const char *class_name; edict_t *pEdict; int element = 0; @@ -1353,11 +1336,6 @@ static cell_t GetEntPropFloat(IPluginContext *pContext, const cell_t *params) return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]); } - if (!pEdict || (class_name = pEdict->GetClassName()) == NULL) - { - class_name = ""; - } - pContext->LocalToString(params[3], &prop); switch (params[2]) @@ -1404,7 +1382,6 @@ static cell_t SetEntPropFloat(IPluginContext *pContext, const cell_t *params) char *prop; int offset; int bit_count; - const char *class_name; edict_t *pEdict; int element = 0; @@ -1418,11 +1395,6 @@ static cell_t SetEntPropFloat(IPluginContext *pContext, const cell_t *params) return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]); } - if (!pEdict || (class_name = pEdict->GetClassName()) == NULL) - { - class_name = ""; - } - pContext->LocalToString(params[3], &prop); switch (params[2]) @@ -1474,7 +1446,6 @@ static cell_t GetEntPropEnt(IPluginContext *pContext, const cell_t *params) char *prop; int offset; int bit_count; - const char *class_name; edict_t *pEdict; int element = 0; @@ -1488,11 +1459,6 @@ static cell_t GetEntPropEnt(IPluginContext *pContext, const cell_t *params) return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]); } - if (!pEdict || (class_name = pEdict->GetClassName()) == NULL) - { - class_name = ""; - } - pContext->LocalToString(params[3], &prop); switch (params[2]) @@ -1538,7 +1504,6 @@ static cell_t SetEntPropEnt(IPluginContext *pContext, const cell_t *params) char *prop; int offset; int bit_count; - const char *class_name; edict_t *pEdict; int element = 0; @@ -1552,11 +1517,6 @@ static cell_t SetEntPropEnt(IPluginContext *pContext, const cell_t *params) return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]); } - if (!pEdict || (class_name = pEdict->GetClassName()) == NULL) - { - class_name = ""; - } - pContext->LocalToString(params[3], &prop); switch (params[2]) @@ -1623,7 +1583,6 @@ static cell_t GetEntPropVector(IPluginContext *pContext, const cell_t *params) char *prop; int offset; int bit_count; - const char *class_name; edict_t *pEdict; int element = 0; @@ -1637,11 +1596,6 @@ static cell_t GetEntPropVector(IPluginContext *pContext, const cell_t *params) return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]); } - if (!pEdict || (class_name = pEdict->GetClassName()) == NULL) - { - class_name = ""; - } - pContext->LocalToString(params[3], &prop); switch (params[2]) @@ -1695,7 +1649,6 @@ static cell_t SetEntPropVector(IPluginContext *pContext, const cell_t *params) char *prop; int offset; int bit_count; - const char *class_name; edict_t *pEdict; int element = 0; @@ -1709,11 +1662,6 @@ static cell_t SetEntPropVector(IPluginContext *pContext, const cell_t *params) return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]); } - if (!pEdict || (class_name = pEdict->GetClassName()) == NULL) - { - class_name = ""; - } - pContext->LocalToString(params[3], &prop); switch (params[2]) @@ -1771,7 +1719,6 @@ static cell_t GetEntPropString(IPluginContext *pContext, const cell_t *params) CBaseEntity *pEntity; char *prop; int offset; - const char *class_name; edict_t *pEdict; bool bIsStringIndex; @@ -1786,11 +1733,6 @@ static cell_t GetEntPropString(IPluginContext *pContext, const cell_t *params) return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]); } - if (!pEdict || (class_name = pEdict->GetClassName()) == NULL) - { - class_name = ""; - } - pContext->LocalToString(params[3], &prop); bIsStringIndex = false; @@ -1849,10 +1791,11 @@ static cell_t GetEntPropString(IPluginContext *pContext, const cell_t *params) } if (!g_HL2.FindSendPropInfo(pNet->GetServerClass()->GetName(), prop, &info)) { + const char *class_name = g_HL2.GetEntityClassname(pEntity); return pContext->ThrowNativeError("Property \"%s\" not found (entity %d/%s)", prop, params[1], - class_name); + ((class_name) ? class_name : "")); } offset = info.actual_offset; diff --git a/public/IGameHelpers.h b/public/IGameHelpers.h index 08f817f4..4e165d7e 100644 --- a/public/IGameHelpers.h +++ b/public/IGameHelpers.h @@ -40,7 +40,7 @@ */ #define SMINTERFACE_GAMEHELPERS_NAME "IGameHelpers" -#define SMINTERFACE_GAMEHELPERS_VERSION 8 +#define SMINTERFACE_GAMEHELPERS_VERSION 9 class CBaseEntity; class CBaseHandle; @@ -292,6 +292,22 @@ namespace SourceMod * @return ICommandLine ptr or NULL if not found. */ virtual ICommandLine *GetValveCommandLine() =0; + + /** + * @brief Gets a Classname from an edict_t pointer. + * + * @param pEdict edict_t pointer. + * @return Pointer to the string, or NULL if bad pointer. + */ + virtual const char *GetEntityClassname(edict_t *pEdict) =0; + + /** + * @brief Gets a Classname from an CBaseEntity pointer. + * + * @param pEntity CBaseEntity pointer. + * @return Pointer to the string, or NULL if bad pointer. + */ + virtual const char *GetEntityClassname(CBaseEntity *pEntity) =0; }; }