Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

forget_memory opcode #53

Merged
merged 3 commits into from
Jan 6, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 ([forget_memory](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
Expand Down
58 changes: 52 additions & 6 deletions source/CCustomOpcodeSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,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); // forget_memory

typedef void(*FuncScriptDeleteDelegateT) (CRunningScript *script);
struct ScriptDeleteDelegate {
Expand Down Expand Up @@ -406,6 +407,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); // forget_memory
}

void CCustomOpcodeSystem::Inject(CCodeInjector& inj)
Expand Down Expand Up @@ -2472,10 +2474,21 @@ namespace CLEO
//0AC8=2,%2d% = allocate_memory_size %1d%
OpcodeResult __stdcall opcode_0AC8(CRunningScript *thread)
{
DWORD size;
*thread >> size;
void *mem = malloc(size);
if (mem) GetInstance().OpcodeSystem.m_pAllocations.insert(mem);
DWORD size; *thread >> size;

void* mem = malloc(size);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we switch over to calloc here? I'm not sure how breaking this change might be, but I couldn't imagine any script specifically relying on uninitialized memory

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reasonable. Updated.

if (mem)
{
DWORD oldProtect;
VirtualProtect(mem, size, PAGE_EXECUTE_READWRITE, &oldProtect);

GetInstance().OpcodeSystem.m_pAllocations.insert(mem);
}
else
{
LOG_WARNING(thread, "[0AC8] failed to allocate %d bytes of memory in script %s", size, ((CCustomScript*)thread)->GetInfoStr().c_str());
}

*thread << mem;
SetScriptCondResult(thread, mem != nullptr);
return OR_CONTINUE;
Expand All @@ -2484,14 +2497,24 @@ 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
}

LOG_WARNING(thread, "[0AC9] used with pointer to unknown or already freed memory in script %s", ((CCustomScript*)thread)->GetInfoStr().c_str());
return OR_CONTINUE;
}

Expand Down Expand Up @@ -3109,6 +3132,29 @@ namespace CLEO
SetScriptCondResult(thread, false);
return GetInstance().OpcodeSystem.CleoReturnGeneric(0x2003, thread);
}

//2004=1,forget_memory %1d%
OpcodeResult __stdcall opcode_2004(CRunningScript* thread)
{
void* mem; *thread >> mem;

if ((size_t)mem <= CCustomOpcodeSystem::MinValidAddress)
{
SHOW_ERROR("[2004] 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())
{
allocs.erase(mem);
return OR_CONTINUE; // done
}

LOG_WARNING(thread, "[2004] used with pointer to unknown or already freed memory in script %s", ((CCustomScript*)thread)->GetInfoStr().c_str());
return OR_CONTINUE;
}
}


Expand Down
1 change: 1 addition & 0 deletions source/CCustomOpcodeSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ 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);

std::set<DWORD> m_hFiles;
std::set<HMODULE> m_hNativeLibs;
Expand Down