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

View File

@ -18,6 +18,7 @@ struct ValveCall
ValvePassInfo *retinfo; /**< Return buffer info */
ValvePassInfo *thisinfo; /**< Thiscall info */
size_t stackSize; /**< Stack size */
size_t stackEnd; /**< End of the bintools stack */
unsigned char *retbuf; /**< Return buffer */
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,
params[startparam],
vc,
vc->thisinfo,
ptr) == Data_Fail)
{
@ -268,8 +269,9 @@ static cell_t SDKCall(IPluginContext *pContext, const cell_t *params)
}
if (DecodeValveParam(pContext,
params[p],
vc,
&(vc->vparams[i]),
ptr + vc->vparams[i].offset) == Data_Fail)
ptr) == Data_Fail)
{
vc->stk_put(ptr);
return 0;
@ -292,8 +294,9 @@ static cell_t SDKCall(IPluginContext *pContext, const cell_t *params)
{
if (EncodeValveParam(pContext,
startparam + i,
vc,
&vc->vparams[i],
ptr + vc->vparams[i].offset) == Data_Fail)
ptr) == Data_Fail)
{
vc->stk_put(ptr);
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");
}
if (EncodeValveParam(pContext, params[retparam], vc->retinfo, vc->retbuf)
if (EncodeValveParam(pContext, params[retparam], vc, vc->retinfo, vc->retbuf)
== Data_Fail)
{
return 0;

View File

@ -1,13 +1,14 @@
#include "smsdk_ext.h"
#include "extension.h"
#include "vdecoder.h"
#include "vcallbuilder.h"
using namespace SourceMod;
using namespace SourcePawn;
/**
* 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
*
* 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,
PassType pass,
unsigned int flags,
PassInfo *info)
PassInfo *info,
bool &needs_extra)
{
needs_extra = false;
switch (type)
{
case Valve_Vector:
@ -34,7 +37,8 @@ size_t ValveParamToBinParam(ValveType type,
info->type = PassType_Basic;
info->flags = flags;
info->size = sizeof(Vector *);
mySize += sizeof(Vector);
mySize = sizeof(Vector);
needs_extra = true;
} else if (pass == PassType_Object) {
info->type = PassType_Object;
info->flags = flags | PASSFLAG_OASSIGNOP | PASSFLAG_OCTOR;
@ -56,7 +60,8 @@ size_t ValveParamToBinParam(ValveType type,
info->type = PassType_Basic;
info->flags = flags;
info->size = sizeof(QAngle *);
mySize += sizeof(QAngle);
mySize = sizeof(QAngle);
needs_extra = true;
} else if (pass == PassType_Object) {
info->type = PassType_Object;
info->flags = flags | PASSFLAG_OASSIGNOP | PASSFLAG_OCTOR;
@ -126,9 +131,11 @@ size_t ValveParamToBinParam(ValveType type,
DataStatus EncodeValveParam(IPluginContext *pContext,
cell_t param,
const ValveCall *pCall,
const ValvePassInfo *data,
const void *buffer)
const void *_buffer)
{
const void *buffer = (const unsigned char *)_buffer + data->offset;
switch (data->vtype)
{
case Valve_Vector:
@ -239,9 +246,11 @@ DataStatus EncodeValveParam(IPluginContext *pContext,
DataStatus DecodeValveParam(IPluginContext *pContext,
cell_t param,
const ValveCall *pCall,
const ValvePassInfo *data,
void *buffer)
void *_buffer)
{
void *buffer = (unsigned char *)_buffer + data->offset;
switch (data->vtype)
{
case Valve_Vector:
@ -269,7 +278,7 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
return Data_Fail;
}
} else {
mem += sizeof(Vector *);
mem = (unsigned char *)_buffer + pCall->stackEnd + data->obj_offset;
*realPtr = (Vector *)mem;
}
}
@ -316,7 +325,7 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
return Data_Okay;
}
} else {
mem += sizeof(QAngle *);
mem = (unsigned char *)_buffer + pCall->stackEnd + data->obj_offset;
*realPtr = (QAngle *)mem;
}
}

View File

@ -60,8 +60,11 @@ struct ValvePassInfo
PassType type; /**< IN: Pass information */
unsigned int flags; /**< IN: Pass flags */
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.
*
@ -75,7 +78,8 @@ struct ValvePassInfo
size_t ValveParamToBinParam(ValveType type,
PassType pass,
unsigned int flags,
PassInfo *info);
PassInfo *info,
bool &needs_extra);
/**
* @brief Decodes data from a plugin to native data.
@ -90,6 +94,7 @@ size_t ValveParamToBinParam(ValveType type,
*/
DataStatus DecodeValveParam(IPluginContext *pContext,
cell_t param,
const ValveCall *pCall,
const ValvePassInfo *vdata,
void *buffer);
@ -106,6 +111,7 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
*/
DataStatus EncodeValveParam(IPluginContext *pContext,
cell_t param,
const ValveCall *pCall,
const ValvePassInfo *vdata,
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) \
if (EncodeValveParam(pContext, \
params[num], \
pCall, \
&pCall->which[vnum], \
vptr + pCall->which[vnum].offset) \
vptr) \
== Data_Fail) \
{ \
return 0; \
@ -33,8 +34,9 @@ inline void InitPass(ValvePassInfo &info, ValveType vtype, PassType type, unsign
#define DECODE_VALVE_PARAM(num, which, vnum) \
if (DecodeValveParam(pContext, \
params[num], \
pCall, \
&pCall->which[vnum], \
vptr + pCall->which[vnum].offset) \
vptr) \
== Data_Fail) \
{ \
return 0; \