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:
parent
c2d1cc5ab5
commit
e29e6c216e
@ -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, ¶mBuf[i])) == 0)
|
||||
bool needs_extra;
|
||||
if ((size = ValveParamToBinParam(params[i].vtype,
|
||||
params[i].type,
|
||||
params[i].flags,
|
||||
¶mBuf[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, ¶mBuf[i])) == 0)
|
||||
bool needs_extra;
|
||||
if ((size = ValveParamToBinParam(params[i].vtype,
|
||||
params[i].type,
|
||||
params[i].flags,
|
||||
¶mBuf[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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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; \
|
||||
|
Loading…
Reference in New Issue
Block a user