fixed a very serious flaw where Vectors being passed as pointers would corrupt the vector object values. this caused TeleportEntity() to have very weird effects

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40993
This commit is contained in:
David Anderson 2007-06-20 08:03:43 +00:00
parent c2d1cc5ab5
commit e29e6c216e
6 changed files with 103 additions and 26 deletions

View File

@ -60,17 +60,22 @@ ValveCall *CreateValveCall(void *addr,
size_t size = 0; size_t size = 0;
vc->stackSize = 0; vc->stackSize = 0;
/* Get return information - encode only*/ /* Get return information - encode only */
PassInfo retBuf; PassInfo retBuf;
size_t retBufSize = 0; size_t retBufSize = 0;
bool retbuf_needs_extra;
if (retInfo) if (retInfo)
{ {
if ((size = ValveParamToBinParam(retInfo->vtype, retInfo->type, retInfo->flags, &retBuf)) == 0) if ((size = ValveParamToBinParam(retInfo->vtype, retInfo->type, retInfo->flags, &retBuf, retbuf_needs_extra)) == 0)
{ {
delete vc; delete vc;
return NULL; return NULL;
} }
retBufSize = size; retBufSize = retBuf.size;
if (retbuf_needs_extra)
{
retBufSize += size;
}
} }
/* Get thisinfo if needed */ /* Get thisinfo if needed */
@ -98,14 +103,29 @@ ValveCall *CreateValveCall(void *addr,
/* Get parameter info */ /* Get parameter info */
PassInfo paramBuf[32]; PassInfo paramBuf[32];
size_t sizes[32];
size_t normSize = 0;
size_t extraSize = 0;
for (unsigned int i=0; i<numParams; i++) for (unsigned int i=0; i<numParams; i++)
{ {
if ((size = ValveParamToBinParam(params[i].vtype, params[i].type, params[i].flags, &paramBuf[i])) == 0) bool needs_extra;
if ((size = ValveParamToBinParam(params[i].vtype,
params[i].type,
params[i].flags,
&paramBuf[i],
needs_extra)) == 0)
{ {
delete vc; delete vc;
return NULL; return NULL;
} }
vc->stackSize += size; if (needs_extra)
{
sizes[i] = size;
} else {
sizes[i] = 0;
}
normSize += paramBuf[i].size;
extraSize += sizes[i];
} }
/* Now we can try creating the call */ /* Now we can try creating the call */
@ -135,6 +155,7 @@ ValveCall *CreateValveCall(void *addr,
vc->retinfo = &(vc->vparams[numParams]); vc->retinfo = &(vc->vparams[numParams]);
*vc->retinfo = *retInfo; *vc->retinfo = *retInfo;
vc->retinfo->offset = 0; vc->retinfo->offset = 0;
vc->retinfo->obj_offset = retbuf_needs_extra ? sizeof(void *) : 0;
/* Allocate stack space */ /* Allocate stack space */
vc->retbuf = new unsigned char[retBufSize]; vc->retbuf = new unsigned char[retBufSize];
} else { } else {
@ -148,18 +169,25 @@ ValveCall *CreateValveCall(void *addr,
vc->thisinfo = &(vc->vparams[numParams + 1]); vc->thisinfo = &(vc->vparams[numParams + 1]);
*vc->thisinfo = *thisinfo; *vc->thisinfo = *thisinfo;
vc->thisinfo->offset = 0; vc->thisinfo->offset = 0;
vc->thisinfo->obj_offset = 0;
} else { } else {
vc->thisinfo = NULL; vc->thisinfo = NULL;
} }
/* Now, save info about each parameter. */ /* Now, save info about each parameter. */
size_t last_extra_offset = 0;
for (unsigned int i=0; i<numParams; i++) for (unsigned int i=0; i<numParams; i++)
{ {
/* Copy */ /* Copy */
vc->vparams[i] = params[i]; vc->vparams[i] = params[i];
vc->vparams[i].offset = vc->call->GetParamInfo(i)->offset; vc->vparams[i].offset = vc->call->GetParamInfo(i)->offset;
vc->vparams[i].obj_offset = last_extra_offset;
last_extra_offset += sizes[i];
} }
vc->stackSize = normSize + extraSize;
vc->stackEnd = normSize;
return vc; return vc;
} }
@ -179,29 +207,49 @@ ValveCall *CreateValveVCall(unsigned int vtableIdx,
size_t size = 0; size_t size = 0;
vc->stackSize = 0; vc->stackSize = 0;
/* Get return information - encode only*/ /* Get return information - encode only */
PassInfo retBuf; PassInfo retBuf;
size_t retBufSize = 0; size_t retBufSize = 0;
bool retbuf_needs_extra;
if (retInfo) if (retInfo)
{ {
if ((size = ValveParamToBinParam(retInfo->vtype, retInfo->type, retInfo->flags, &retBuf)) == 0) if ((size = ValveParamToBinParam(retInfo->vtype, retInfo->type, retInfo->flags, &retBuf, retbuf_needs_extra)) == 0)
{ {
delete vc; delete vc;
return NULL; return NULL;
} }
retBufSize = size; retBufSize = retBuf.size;
if (retbuf_needs_extra)
{
retBufSize += size;
}
} }
/* Get parameter info */ /* Get parameter info */
PassInfo paramBuf[32]; PassInfo paramBuf[32];
size_t sizes[32];
size_t normSize = 0;
size_t extraSize = 0;
for (unsigned int i=0; i<numParams; i++) for (unsigned int i=0; i<numParams; i++)
{ {
if ((size = ValveParamToBinParam(params[i].vtype, params[i].type, params[i].flags, &paramBuf[i])) == 0) bool needs_extra;
if ((size = ValveParamToBinParam(params[i].vtype,
params[i].type,
params[i].flags,
&paramBuf[i],
needs_extra)) == 0)
{ {
delete vc; delete vc;
return NULL; return NULL;
} }
vc->stackSize += size; if (needs_extra)
{
sizes[i] = size;
} else {
sizes[i] = 0;
}
normSize += paramBuf[i].size;
extraSize += sizes[i];
} }
/* Now we can try creating the call */ /* Now we can try creating the call */
@ -232,6 +280,7 @@ ValveCall *CreateValveVCall(unsigned int vtableIdx,
vc->retinfo = &(vc->vparams[numParams]); vc->retinfo = &(vc->vparams[numParams]);
*vc->retinfo = *retInfo; *vc->retinfo = *retInfo;
vc->retinfo->offset = 0; vc->retinfo->offset = 0;
vc->retinfo->obj_offset = retbuf_needs_extra ? sizeof(void *) : 0;
/* Allocate stack space */ /* Allocate stack space */
vc->retbuf = new unsigned char[retBufSize]; vc->retbuf = new unsigned char[retBufSize];
} else { } else {
@ -253,15 +302,22 @@ ValveCall *CreateValveVCall(unsigned int vtableIdx,
vc->thisinfo->encflags = 0; vc->thisinfo->encflags = 0;
vc->thisinfo->flags = PASSFLAG_BYVAL; vc->thisinfo->flags = PASSFLAG_BYVAL;
vc->thisinfo->offset = 0; vc->thisinfo->offset = 0;
vc->stackSize += sizeof(void *); vc->thisinfo->obj_offset = 0;
normSize += sizeof(void *);
/* Now, save info about each parameter. */ /* Now, save info about each parameter. */
size_t last_extra_offset = 0;
for (unsigned int i=0; i<numParams; i++) for (unsigned int i=0; i<numParams; i++)
{ {
/* Copy */ /* Copy */
vc->vparams[i] = params[i]; vc->vparams[i] = params[i];
vc->vparams[i].offset = vc->call->GetParamInfo(i)->offset; vc->vparams[i].offset = vc->call->GetParamInfo(i)->offset;
vc->vparams[i].obj_offset = last_extra_offset;
last_extra_offset += sizes[i];
} }
vc->stackSize = normSize + extraSize;
vc->stackEnd = normSize;
return vc; return vc;
} }

View File

@ -18,6 +18,7 @@ struct ValveCall
ValvePassInfo *retinfo; /**< Return buffer info */ ValvePassInfo *retinfo; /**< Return buffer info */
ValvePassInfo *thisinfo; /**< Thiscall info */ ValvePassInfo *thisinfo; /**< Thiscall info */
size_t stackSize; /**< Stack size */ size_t stackSize; /**< Stack size */
size_t stackEnd; /**< End of the bintools stack */
unsigned char *retbuf; /**< Return buffer */ unsigned char *retbuf; /**< Return buffer */
CStack<unsigned char *> stk; /**< Parameter stack */ CStack<unsigned char *> stk; /**< Parameter stack */

View File

@ -233,6 +233,7 @@ static cell_t SDKCall(IPluginContext *pContext, const cell_t *params)
} }
if (DecodeValveParam(pContext, if (DecodeValveParam(pContext,
params[startparam], params[startparam],
vc,
vc->thisinfo, vc->thisinfo,
ptr) == Data_Fail) ptr) == Data_Fail)
{ {
@ -268,8 +269,9 @@ static cell_t SDKCall(IPluginContext *pContext, const cell_t *params)
} }
if (DecodeValveParam(pContext, if (DecodeValveParam(pContext,
params[p], params[p],
vc,
&(vc->vparams[i]), &(vc->vparams[i]),
ptr + vc->vparams[i].offset) == Data_Fail) ptr) == Data_Fail)
{ {
vc->stk_put(ptr); vc->stk_put(ptr);
return 0; return 0;
@ -292,8 +294,9 @@ static cell_t SDKCall(IPluginContext *pContext, const cell_t *params)
{ {
if (EncodeValveParam(pContext, if (EncodeValveParam(pContext,
startparam + i, startparam + i,
vc,
&vc->vparams[i], &vc->vparams[i],
ptr + vc->vparams[i].offset) == Data_Fail) ptr) == Data_Fail)
{ {
vc->stk_put(ptr); vc->stk_put(ptr);
return 0; return 0;
@ -326,7 +329,7 @@ static cell_t SDKCall(IPluginContext *pContext, const cell_t *params)
{ {
return pContext->ThrowNativeError("Expected argument (2) for Float[3] storage"); return pContext->ThrowNativeError("Expected argument (2) for Float[3] storage");
} }
if (EncodeValveParam(pContext, params[retparam], vc->retinfo, vc->retbuf) if (EncodeValveParam(pContext, params[retparam], vc, vc->retinfo, vc->retbuf)
== Data_Fail) == Data_Fail)
{ {
return 0; return 0;

View File

@ -1,13 +1,14 @@
#include "smsdk_ext.h" #include "smsdk_ext.h"
#include "extension.h" #include "extension.h"
#include "vdecoder.h" #include "vdecoder.h"
#include "vcallbuilder.h"
using namespace SourceMod; using namespace SourceMod;
using namespace SourcePawn; using namespace SourcePawn;
/** /**
* For object pointers, the data looks like this instead: * For object pointers, the data looks like this instead:
* 4 bytes: POINTER TO NEXT FOUR BYTES * 4 bytes: POINTER TO LATER
* + bytes: Object internal data * + bytes: Object internal data
* *
* We use the virtual stack as extra fake stack space and create a temp object. * We use the virtual stack as extra fake stack space and create a temp object.
@ -18,8 +19,10 @@ using namespace SourcePawn;
size_t ValveParamToBinParam(ValveType type, size_t ValveParamToBinParam(ValveType type,
PassType pass, PassType pass,
unsigned int flags, unsigned int flags,
PassInfo *info) PassInfo *info,
bool &needs_extra)
{ {
needs_extra = false;
switch (type) switch (type)
{ {
case Valve_Vector: case Valve_Vector:
@ -34,7 +37,8 @@ size_t ValveParamToBinParam(ValveType type,
info->type = PassType_Basic; info->type = PassType_Basic;
info->flags = flags; info->flags = flags;
info->size = sizeof(Vector *); info->size = sizeof(Vector *);
mySize += sizeof(Vector); mySize = sizeof(Vector);
needs_extra = true;
} else if (pass == PassType_Object) { } else if (pass == PassType_Object) {
info->type = PassType_Object; info->type = PassType_Object;
info->flags = flags | PASSFLAG_OASSIGNOP | PASSFLAG_OCTOR; info->flags = flags | PASSFLAG_OASSIGNOP | PASSFLAG_OCTOR;
@ -56,7 +60,8 @@ size_t ValveParamToBinParam(ValveType type,
info->type = PassType_Basic; info->type = PassType_Basic;
info->flags = flags; info->flags = flags;
info->size = sizeof(QAngle *); info->size = sizeof(QAngle *);
mySize += sizeof(QAngle); mySize = sizeof(QAngle);
needs_extra = true;
} else if (pass == PassType_Object) { } else if (pass == PassType_Object) {
info->type = PassType_Object; info->type = PassType_Object;
info->flags = flags | PASSFLAG_OASSIGNOP | PASSFLAG_OCTOR; info->flags = flags | PASSFLAG_OASSIGNOP | PASSFLAG_OCTOR;
@ -126,9 +131,11 @@ size_t ValveParamToBinParam(ValveType type,
DataStatus EncodeValveParam(IPluginContext *pContext, DataStatus EncodeValveParam(IPluginContext *pContext,
cell_t param, cell_t param,
const ValveCall *pCall,
const ValvePassInfo *data, const ValvePassInfo *data,
const void *buffer) const void *_buffer)
{ {
const void *buffer = (const unsigned char *)_buffer + data->offset;
switch (data->vtype) switch (data->vtype)
{ {
case Valve_Vector: case Valve_Vector:
@ -239,9 +246,11 @@ DataStatus EncodeValveParam(IPluginContext *pContext,
DataStatus DecodeValveParam(IPluginContext *pContext, DataStatus DecodeValveParam(IPluginContext *pContext,
cell_t param, cell_t param,
const ValveCall *pCall,
const ValvePassInfo *data, const ValvePassInfo *data,
void *buffer) void *_buffer)
{ {
void *buffer = (unsigned char *)_buffer + data->offset;
switch (data->vtype) switch (data->vtype)
{ {
case Valve_Vector: case Valve_Vector:
@ -269,7 +278,7 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
return Data_Fail; return Data_Fail;
} }
} else { } else {
mem += sizeof(Vector *); mem = (unsigned char *)_buffer + pCall->stackEnd + data->obj_offset;
*realPtr = (Vector *)mem; *realPtr = (Vector *)mem;
} }
} }
@ -316,7 +325,7 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
return Data_Okay; return Data_Okay;
} }
} else { } else {
mem += sizeof(QAngle *); mem = (unsigned char *)_buffer + pCall->stackEnd + data->obj_offset;
*realPtr = (QAngle *)mem; *realPtr = (QAngle *)mem;
} }
} }

View File

@ -60,8 +60,11 @@ struct ValvePassInfo
PassType type; /**< IN: Pass information */ PassType type; /**< IN: Pass information */
unsigned int flags; /**< IN: Pass flags */ unsigned int flags; /**< IN: Pass flags */
size_t offset; /**< OUT: stack offset */ size_t offset; /**< OUT: stack offset */
size_t obj_offset; /**< OUT: object offset at end of the stack */
}; };
struct ValveCall;
/** /**
* @brief Converts a valve parameter to a bintools parameter. * @brief Converts a valve parameter to a bintools parameter.
* *
@ -75,7 +78,8 @@ struct ValvePassInfo
size_t ValveParamToBinParam(ValveType type, size_t ValveParamToBinParam(ValveType type,
PassType pass, PassType pass,
unsigned int flags, unsigned int flags,
PassInfo *info); PassInfo *info,
bool &needs_extra);
/** /**
* @brief Decodes data from a plugin to native data. * @brief Decodes data from a plugin to native data.
@ -90,6 +94,7 @@ size_t ValveParamToBinParam(ValveType type,
*/ */
DataStatus DecodeValveParam(IPluginContext *pContext, DataStatus DecodeValveParam(IPluginContext *pContext,
cell_t param, cell_t param,
const ValveCall *pCall,
const ValvePassInfo *vdata, const ValvePassInfo *vdata,
void *buffer); void *buffer);
@ -106,6 +111,7 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
*/ */
DataStatus EncodeValveParam(IPluginContext *pContext, DataStatus EncodeValveParam(IPluginContext *pContext,
cell_t param, cell_t param,
const ValveCall *pCall,
const ValvePassInfo *vdata, const ValvePassInfo *vdata,
const void *buffer); const void *buffer);

View File

@ -23,8 +23,9 @@ inline void InitPass(ValvePassInfo &info, ValveType vtype, PassType type, unsign
#define ENCODE_VALVE_PARAM(num, which, vnum) \ #define ENCODE_VALVE_PARAM(num, which, vnum) \
if (EncodeValveParam(pContext, \ if (EncodeValveParam(pContext, \
params[num], \ params[num], \
pCall, \
&pCall->which[vnum], \ &pCall->which[vnum], \
vptr + pCall->which[vnum].offset) \ vptr) \
== Data_Fail) \ == Data_Fail) \
{ \ { \
return 0; \ return 0; \
@ -33,8 +34,9 @@ inline void InitPass(ValvePassInfo &info, ValveType vtype, PassType type, unsign
#define DECODE_VALVE_PARAM(num, which, vnum) \ #define DECODE_VALVE_PARAM(num, which, vnum) \
if (DecodeValveParam(pContext, \ if (DecodeValveParam(pContext, \
params[num], \ params[num], \
pCall, \
&pCall->which[vnum], \ &pCall->which[vnum], \
vptr + pCall->which[vnum].offset) \ vptr) \
== Data_Fail) \ == Data_Fail) \
{ \ { \
return 0; \ return 0; \