mirror of
https://github.com/cemu-project/Cemu.git
synced 2026-11-12 09:08:51 +01:00
PPCRec: Fix function scanning reading unmapped memory
Scanning code near the start or end of a codecave could read past its memory region and crash.
This commit is contained in:
1 parent
0e4fc41f20
commit
d1ca2e987f
1 file changed
+14
-4
@@ -76,6 +76,9 @@ public:
|
||||
private:
|
||||
void addBranchDestination(PPCRange_t* sourceRange, MPTR address)
|
||||
{
|
||||
// data that gets scanned as code can decode as a branch to unmapped memory
|
||||
if (!memory_isAddressRangeAccessible(address, 4))
|
||||
return;
|
||||
map_queuedBranchTargets.emplace(address);
|
||||
map_branchTargetsAll.emplace(address);
|
||||
}
|
||||
@@ -131,8 +134,8 @@ private:
|
||||
// if the next two or previous two instructions are branch instructions, we assume that they are destinations of a jump table
|
||||
// todo - can we make this more reliable by checking for BCTR or similar instructions first?
|
||||
// example: The Swapper 0x01B1FC04
|
||||
if (PPCRecompilerCalcFuncSize_isUnconditionalBranchInstruction(memory_readU32(address + 4)) && PPCRecompilerCalcFuncSize_isUnconditionalBranchInstruction(memory_readU32(address + 8)) ||
|
||||
PPCRecompilerCalcFuncSize_isUnconditionalBranchInstruction(memory_readU32(address - 8)) && PPCRecompilerCalcFuncSize_isUnconditionalBranchInstruction(memory_readU32(address - 4)))
|
||||
if (PPCRecompilerCalcFuncSize_isUnconditionalBranchInstruction(address + 4) && PPCRecompilerCalcFuncSize_isUnconditionalBranchInstruction(address + 8) ||
|
||||
PPCRecompilerCalcFuncSize_isUnconditionalBranchInstruction(address - 8) && PPCRecompilerCalcFuncSize_isUnconditionalBranchInstruction(address - 4))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -165,7 +168,7 @@ private:
|
||||
|
||||
// Currently we only end the function if the BCTR is followed by a NOP (alignment) or invalid instruction
|
||||
// todo: improve robustness, find better ways to handle false positives
|
||||
uint32 nextOpcode = memory_readU32(address + 4);
|
||||
uint32 nextOpcode = memory_isAddressRangeAccessible(address + 4, 4) ? memory_readU32(address + 4) : 0;
|
||||
|
||||
if (nextOpcode == 0x60000000 || PPCRecompilerCalcFuncSize_isValidInstruction(nextOpcode) == false)
|
||||
{
|
||||
@@ -221,6 +224,9 @@ private:
|
||||
MPTR endAddress = 0xFFFFFFFF;
|
||||
if (nextRange)
|
||||
endAddress = nextRange->startAddress;
|
||||
// don't scan past the end of the mapped region
|
||||
if (MMURange* mmuRange = memory_getMMURangeByAddress(startAddress); mmuRange && mmuRange->getEnd() < endAddress)
|
||||
endAddress = mmuRange->getEnd();
|
||||
while (currentAddress < endAddress)
|
||||
{
|
||||
if (!processInstruction(newRange, currentAddress))
|
||||
@@ -293,8 +299,12 @@ private:
|
||||
}
|
||||
|
||||
private:
|
||||
bool PPCRecompilerCalcFuncSize_isUnconditionalBranchInstruction(uint32 opcode)
|
||||
bool PPCRecompilerCalcFuncSize_isUnconditionalBranchInstruction(MPTR address)
|
||||
{
|
||||
// neighbours can be unmapped
|
||||
if (!memory_isAddressRangeAccessible(address, 4))
|
||||
return false;
|
||||
uint32 opcode = memory_readU32(address);
|
||||
if (Espresso::GetPrimaryOpcode(opcode) == Espresso::PrimaryOpcode::B)
|
||||
{
|
||||
uint32 LI;
|
||||
|
||||
Reference in new issue
Block a user