Skip to content

Commit

Permalink
Removed size validations from opcode 0AD7
Browse files Browse the repository at this point in the history
  • Loading branch information
MiranDMC committed Mar 3, 2024
1 parent 1a7da50 commit f3264fb
Showing 1 changed file with 2 additions and 60 deletions.
62 changes: 2 additions & 60 deletions cleo_plugins/FileSystemOperations/FileSystemOperations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@ class FileSystemOperations
{
auto handle = READ_FILE_HANDLE_PARAM();

auto resultParamType = thread->PeekDataType();
char* buffer = nullptr;
int bufferSize = 0;
DWORD needsTerminator = TRUE;
Expand All @@ -312,66 +311,9 @@ class FileSystemOperations
return OR_CONTINUE;
}

std::vector<char> tmpBuff;
tmpBuff.resize(size);
auto data = tmpBuff.data();
bool ok = File::readString(handle, buffer, size) != nullptr;

bool ok = File::readString(handle, data, size) != nullptr;
if (!ok)
{
OPCODE_CONDITION_RESULT(false);
return OR_CONTINUE;
}

// In older CLEO this opcode only accepted output as reference to short/long string variables.
// If user wanted to load string into memory address, the only way was some variable array with carefully calculated out-of-bouds index,
// resulting in indexed dummy element to appear under that address. Detect such cases:
bool externalAddress = false;
switch (resultParamType)
{
// global variable array
case DT_VAR_ARRAY:
case DT_VAR_TEXTLABEL:
case DT_VAR_TEXTLABEL_ARRAY:
case DT_VAR_STRING_ARRAY:
{
auto globalsBeg = CTheScripts::ScriptSpace;
auto globalsEnd = globalsBeg + 16381 * sizeof(SCRIPT_VAR); // 16381 is count of global variables for GTA 3/VC/SA/SA-Mobile
externalAddress = buffer < globalsBeg || buffer > globalsEnd;
break;
}

// local variable array
case DT_LVAR_ARRAY:
case DT_LVAR_TEXTLABEL:
case DT_LVAR_TEXTLABEL_ARRAY:
case DT_LVAR_STRING_ARRAY:
{
auto localsBeg = (char*)thread + offsetof(CLEO::CRunningScript, LocalVar);
auto localsEnd = localsBeg + sizeof(CLEO::CRunningScript::LocalVar) + sizeof(CLEO::CRunningScript::Timers); // timers are in fact just two extra local variables
externalAddress = buffer < localsBeg || buffer > localsEnd;
break;
}
}

int resultLen;
if (externalAddress || IsLegacyScript(thread))
{
// ignore target variable's type size restrictions
needsTerminator = true;
resultLen = size - 1; // sapce for terminator
}
else
{
resultLen = bufferSize - (int)needsTerminator;
}

resultLen = min(resultLen, (int)strlen(data));

if (resultLen > 0) memcpy(buffer, data, resultLen);
if (needsTerminator) buffer[resultLen] = '\0';

OPCODE_CONDITION_RESULT(true);
OPCODE_CONDITION_RESULT(ok);
return OR_CONTINUE;
}

Expand Down

0 comments on commit f3264fb

Please sign in to comment.