diff --git a/CHANGELOG.md b/CHANGELOG.md index f489763c..745c4fb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - **2001 ([get_script_filename](https://library.sannybuilder.com/#/sa/CLEO/2001))** - **2002 ([cleo_return_with](https://library.sannybuilder.com/#/sa/CLEO/2002))** - **2003 ([cleo_return_fail](https://library.sannybuilder.com/#/sa/CLEO/2003))** + - **2004 ([allocate_memory_persistent](https://library.sannybuilder.com/#/sa/CLEO/2004))** - 'argument count' parameter of **0AB1 (cleo_call)** is now optional. `cleo_call @LABEL args 0` can be written as `cleo_call @LABEL` - 'argument count' parameter of **0AB2 (cleo_return)** is now optional. `cleo_return 0` can be written as `cleo_return` - opcodes **0AAB**, **0AE4**, **0AE5**, **0AE6**, **0AE7** and **0AE8** moved to the [FileSystemOperations](https://github.com/cleolibrary/CLEO5/tree/master/cleo_plugins/FileSystemOperations) plugin diff --git a/source/CCustomOpcodeSystem.cpp b/source/CCustomOpcodeSystem.cpp index 482dba5b..4e10d414 100644 --- a/source/CCustomOpcodeSystem.cpp +++ b/source/CCustomOpcodeSystem.cpp @@ -129,6 +129,7 @@ namespace CLEO OpcodeResult __stdcall opcode_2001(CRunningScript* thread); // get_script_filename OpcodeResult __stdcall opcode_2002(CRunningScript* thread); // cleo_return_with OpcodeResult __stdcall opcode_2003(CRunningScript* thread); // cleo_return_fail + OpcodeResult __stdcall opcode_2004(CRunningScript* thread); // allocate_memory_persistent typedef void(*FuncScriptDeleteDelegateT) (CRunningScript *script); struct ScriptDeleteDelegate { @@ -443,6 +444,7 @@ namespace CLEO CLEO_RegisterOpcode(0x2001, opcode_2001); // get_script_filename CLEO_RegisterOpcode(0x2002, opcode_2002); // cleo_return_with CLEO_RegisterOpcode(0x2003, opcode_2003); // cleo_return_fail + CLEO_RegisterOpcode(0x2004, opcode_2004); // allocate_memory_persistent } void CCustomOpcodeSystem::Inject(CCodeInjector& inj) @@ -2400,14 +2402,33 @@ namespace CLEO //0AC9=1,free_allocated_memory %1d% OpcodeResult __stdcall opcode_0AC9(CRunningScript *thread) { - void *mem; - *thread >> mem; + void *mem; *thread >> mem; + + if ((size_t)mem <= CCustomOpcodeSystem::MinValidAddress) + { + SHOW_ERROR("[0AC9] used with invalid '0x%X' pointer argument in script %s\nScript suspended.", mem, ((CCustomScript*)thread)->GetInfoStr().c_str()); + return CCustomOpcodeSystem::ErrorSuspendScript(thread); + } + + // allocated with 0AC8 auto & allocs = GetInstance().OpcodeSystem.m_pAllocations; if (allocs.find(mem) != allocs.end()) { free(mem); allocs.erase(mem); + return OR_CONTINUE; // done } + + // allocated with 2004 + auto& allocsPersist = GetInstance().OpcodeSystem.m_pAllocationsPersistent; + if (allocsPersist.find(mem) != allocsPersist.end()) + { + free(mem); + allocsPersist.erase(mem); + return OR_CONTINUE; // done + } + + LOG_WARNING(thread, "[0AC9] used with pointer to unknown or already freed memory in script %s", lastErrorMsg.c_str(), ((CCustomScript*)thread)->GetInfoStr().c_str()); return OR_CONTINUE; } @@ -3032,6 +3053,25 @@ namespace CLEO SetScriptCondResult(thread, false); return CCustomOpcodeSystem::CleoReturnGeneric(0x2003, thread, false); } + + //2004=2, allocate_memory_persistent size %1d% store_to %2d% + OpcodeResult __stdcall opcode_2004(CRunningScript* thread) + { + DWORD size; *thread >> size; + + void* mem = malloc(size); + if (mem) + { + DWORD oldProtect; + VirtualProtect(mem, size, PAGE_EXECUTE_READWRITE, &oldProtect); + + GetInstance().OpcodeSystem.m_pAllocationsPersistent.insert(mem); + } + + SetScriptCondResult(thread, mem != nullptr); + *thread << mem; + return OR_CONTINUE; + } } diff --git a/source/CCustomOpcodeSystem.h b/source/CCustomOpcodeSystem.h index 96913524..8d2d2ca7 100644 --- a/source/CCustomOpcodeSystem.h +++ b/source/CCustomOpcodeSystem.h @@ -39,6 +39,8 @@ namespace CLEO { TRACE("Last opcode executed: %04X", lastOpcode); TRACE("Previous opcode executed: %04X", prevOpcode); + + std::for_each(m_pAllocationsPersistent.begin(), m_pAllocationsPersistent.end(), free); } static bool RegisterOpcode(WORD opcode, CustomOpcodeHandler callback); @@ -53,10 +55,12 @@ namespace CLEO friend OpcodeResult __stdcall opcode_0AA3(CRunningScript *pScript); friend OpcodeResult __stdcall opcode_0AC8(CRunningScript *pScript); friend OpcodeResult __stdcall opcode_0AC9(CRunningScript *pScript); + friend OpcodeResult __stdcall opcode_2004(CRunningScript* pScript); // allocate_memory_persistent std::set m_hFiles; std::set m_hNativeLibs; std::set m_pAllocations; + std::set m_pAllocationsPersistent; typedef OpcodeResult(__thiscall* _OpcodeHandler)(CRunningScript* thread, WORD opcode);