fixed a serious potential bug with swapping plugins to debug mode, leaving stale function pointers without plugin removal

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40508
This commit is contained in:
David Anderson 2007-02-16 04:16:31 +00:00
parent a75e87a076
commit 165b8ed893
4 changed files with 40 additions and 8 deletions

View File

@ -66,30 +66,40 @@ BaseContext::BaseContext(sp_context_t *_ctx)
} }
} }
void BaseContext::FlushFunctionCache() void BaseContext::FlushFunctionCache(bool remove)
{ {
if (m_pub_funcs) if (m_pub_funcs)
{ {
for (uint32_t i=0; i<ctx->plugin->info.publics_num; i++) for (uint32_t i=0; i<ctx->plugin->info.publics_num; i++)
{
if (remove)
{ {
delete m_pub_funcs[i]; delete m_pub_funcs[i];
m_pub_funcs[i] = NULL; m_pub_funcs[i] = NULL;
} else if (m_pub_funcs[i]) {
m_pub_funcs[i]->Invalidate();
}
} }
} }
if (m_priv_funcs) if (m_priv_funcs)
{ {
for (unsigned int i=0; i<m_funcsnum; i++) for (unsigned int i=0; i<m_funcsnum; i++)
{
if (remove)
{ {
delete m_priv_funcs[i]; delete m_priv_funcs[i];
m_priv_funcs[i] = NULL; m_priv_funcs[i] = NULL;
} else if (m_priv_funcs[i]) {
m_priv_funcs[i]->Invalidate();
}
} }
} }
} }
BaseContext::~BaseContext() BaseContext::~BaseContext()
{ {
FlushFunctionCache(); FlushFunctionCache(true);
delete [] m_pub_funcs; delete [] m_pub_funcs;
m_pub_funcs = NULL; m_pub_funcs = NULL;
delete [] m_priv_funcs; delete [] m_priv_funcs;
@ -105,7 +115,7 @@ void BaseContext::SetContext(sp_context_t *_ctx)
ctx = _ctx; ctx = _ctx;
ctx->context = this; ctx->context = this;
ctx->dbreak = GlobalDebugBreak; ctx->dbreak = GlobalDebugBreak;
FlushFunctionCache(); FlushFunctionCache(false);
} }
IVirtualMachine *BaseContext::GetVirtualMachine() IVirtualMachine *BaseContext::GetVirtualMachine()
@ -850,6 +860,8 @@ IPluginFunction *BaseContext::GetFunctionById(funcid_t func_id)
{ {
m_pub_funcs[func_id] = new CFunction(ctx->publics[func_id].code_offs, this); m_pub_funcs[func_id] = new CFunction(ctx->publics[func_id].code_offs, this);
pFunc = m_pub_funcs[func_id]; pFunc = m_pub_funcs[func_id];
} else if (pFunc->IsInvalidated()) {
pFunc->Set(ctx->publics[func_id].code_offs, this);
} }
} else { } else {
/* :TODO: currently not used */ /* :TODO: currently not used */
@ -892,6 +904,15 @@ IPluginFunction *BaseContext::GetFunctionByName(const char *public_name)
m_pub_funcs[index] = new CFunction(pub->code_offs, this); m_pub_funcs[index] = new CFunction(pub->code_offs, this);
} }
pFunc = m_pub_funcs[index]; pFunc = m_pub_funcs[index];
} else if (pFunc->IsInvalidated()) {
sp_public_t *pub = NULL;
GetPublicByIndex(index, &pub);
if (pub)
{
pFunc->Set(pub->code_offs, this);
} else {
pFunc = NULL;
}
} }
return pFunc; return pFunc;

View File

@ -79,7 +79,7 @@ namespace SourcePawn
void SetContext(sp_context_t *_ctx); void SetContext(sp_context_t *_ctx);
private: private:
void SetErrorMessage(const char *msg, va_list ap); void SetErrorMessage(const char *msg, va_list ap);
void FlushFunctionCache(); void FlushFunctionCache(bool remove);
private: private:
sp_context_t *ctx; sp_context_t *ctx;
#if defined SOURCEMOD_BUILD #if defined SOURCEMOD_BUILD

View File

@ -25,6 +25,7 @@ void CFunction::Set(uint32_t code_addr, IPluginContext *plugin)
m_pContext = plugin; m_pContext = plugin;
m_curparam = 0; m_curparam = 0;
m_errorstate = SP_ERROR_NONE; m_errorstate = SP_ERROR_NONE;
m_Invalid = false;
} }
int CFunction::CallFunction(const cell_t *params, unsigned int num_params, cell_t *result) int CFunction::CallFunction(const cell_t *params, unsigned int num_params, cell_t *result)
@ -46,6 +47,7 @@ CFunction::CFunction(uint32_t code_addr, IPluginContext *plugin) :
m_codeaddr(code_addr), m_pContext(plugin), m_curparam(0), m_codeaddr(code_addr), m_pContext(plugin), m_curparam(0),
m_errorstate(SP_ERROR_NONE) m_errorstate(SP_ERROR_NONE)
{ {
m_Invalid = false;
} }
int CFunction::PushCell(cell_t cell) int CFunction::PushCell(cell_t cell)

View File

@ -46,6 +46,14 @@ public:
virtual void Cancel(); virtual void Cancel();
virtual int CallFunction(const cell_t *params, unsigned int num_params, cell_t *result); virtual int CallFunction(const cell_t *params, unsigned int num_params, cell_t *result);
virtual IPluginContext *GetParentContext(); virtual IPluginContext *GetParentContext();
inline bool IsInvalidated()
{
return m_Invalid;
}
inline void Invalidate()
{
m_Invalid = true;
}
public: public:
void Set(uint32_t code_addr, IPluginContext *plugin); void Set(uint32_t code_addr, IPluginContext *plugin);
private: private:
@ -63,6 +71,7 @@ private:
unsigned int m_curparam; unsigned int m_curparam;
int m_errorstate; int m_errorstate;
CFunction *m_pNext; CFunction *m_pNext;
bool m_Invalid;
}; };
#endif //_INCLUDE_SOURCEMOD_BASEFUNCTION_H_ #endif //_INCLUDE_SOURCEMOD_BASEFUNCTION_H_