From 165b8ed893fe7eb3a514e01b5f7ceef01d806666 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Fri, 16 Feb 2007 04:16:31 +0000 Subject: [PATCH] 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 --- core/vm/sp_vm_basecontext.cpp | 35 ++++++++++++++++++++++++++++------- core/vm/sp_vm_basecontext.h | 2 +- core/vm/sp_vm_function.cpp | 2 ++ core/vm/sp_vm_function.h | 9 +++++++++ 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/core/vm/sp_vm_basecontext.cpp b/core/vm/sp_vm_basecontext.cpp index 0107045b..302fb186 100644 --- a/core/vm/sp_vm_basecontext.cpp +++ b/core/vm/sp_vm_basecontext.cpp @@ -66,14 +66,19 @@ BaseContext::BaseContext(sp_context_t *_ctx) } } -void BaseContext::FlushFunctionCache() +void BaseContext::FlushFunctionCache(bool remove) { if (m_pub_funcs) { for (uint32_t i=0; iplugin->info.publics_num; i++) { - delete m_pub_funcs[i]; - m_pub_funcs[i] = NULL; + if (remove) + { + delete m_pub_funcs[i]; + m_pub_funcs[i] = NULL; + } else if (m_pub_funcs[i]) { + m_pub_funcs[i]->Invalidate(); + } } } @@ -81,15 +86,20 @@ void BaseContext::FlushFunctionCache() { for (unsigned int i=0; iInvalidate(); + } } } } BaseContext::~BaseContext() { - FlushFunctionCache(); + FlushFunctionCache(true); delete [] m_pub_funcs; m_pub_funcs = NULL; delete [] m_priv_funcs; @@ -105,7 +115,7 @@ void BaseContext::SetContext(sp_context_t *_ctx) ctx = _ctx; ctx->context = this; ctx->dbreak = GlobalDebugBreak; - FlushFunctionCache(); + FlushFunctionCache(false); } 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); pFunc = m_pub_funcs[func_id]; + } else if (pFunc->IsInvalidated()) { + pFunc->Set(ctx->publics[func_id].code_offs, this); } } else { /* :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); } 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; diff --git a/core/vm/sp_vm_basecontext.h b/core/vm/sp_vm_basecontext.h index 232a7967..4c001a54 100644 --- a/core/vm/sp_vm_basecontext.h +++ b/core/vm/sp_vm_basecontext.h @@ -79,7 +79,7 @@ namespace SourcePawn void SetContext(sp_context_t *_ctx); private: void SetErrorMessage(const char *msg, va_list ap); - void FlushFunctionCache(); + void FlushFunctionCache(bool remove); private: sp_context_t *ctx; #if defined SOURCEMOD_BUILD diff --git a/core/vm/sp_vm_function.cpp b/core/vm/sp_vm_function.cpp index 04ce7a23..c4fc339f 100644 --- a/core/vm/sp_vm_function.cpp +++ b/core/vm/sp_vm_function.cpp @@ -25,6 +25,7 @@ void CFunction::Set(uint32_t code_addr, IPluginContext *plugin) m_pContext = plugin; m_curparam = 0; m_errorstate = SP_ERROR_NONE; + m_Invalid = false; } 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_errorstate(SP_ERROR_NONE) { + m_Invalid = false; } int CFunction::PushCell(cell_t cell) diff --git a/core/vm/sp_vm_function.h b/core/vm/sp_vm_function.h index b61a51fa..2eaaf229 100644 --- a/core/vm/sp_vm_function.h +++ b/core/vm/sp_vm_function.h @@ -46,6 +46,14 @@ public: virtual void Cancel(); virtual int CallFunction(const cell_t *params, unsigned int num_params, cell_t *result); virtual IPluginContext *GetParentContext(); + inline bool IsInvalidated() + { + return m_Invalid; + } + inline void Invalidate() + { + m_Invalid = true; + } public: void Set(uint32_t code_addr, IPluginContext *plugin); private: @@ -63,6 +71,7 @@ private: unsigned int m_curparam; int m_errorstate; CFunction *m_pNext; + bool m_Invalid; }; #endif //_INCLUDE_SOURCEMOD_BASEFUNCTION_H_