MMU/PatchEngine: Fix potential crash during stack probe

TryReadInstruction doesn't validate the address it resolves, that
can result in Memory::GetPointer failing and returning nullptr
which then leads to a nullptr dereference and a crash.

Created PowerPC::HostIsInstructionRAMAddress which works the same
way as PowerPC::HostIsRAMAddress for the IBAT.
This commit is contained in:
EmptyChaos 2017-01-23 21:05:11 +00:00
parent bd2881ff86
commit 49873b1287
3 changed files with 20 additions and 12 deletions

View File

@ -223,11 +223,7 @@ static bool IsStackSane()
return false;
// Check the link register makes sense (that it points to a valid IBAT address)
auto insn = PowerPC::TryReadInstruction(PowerPC::HostRead_U32(next_SP + 4));
if (!insn.valid || !insn.hex)
return false;
return true;
return PowerPC::HostIsInstructionRAMAddress(PowerPC::HostRead_U32(next_SP + 4));
}
bool ApplyFramePatches()

View File

@ -622,19 +622,18 @@ bool IsOptimizableRAMAddress(const u32 address)
return (bat_result & 2) != 0;
}
bool HostIsRAMAddress(u32 address)
template <XCheckTLBFlag flag>
static bool IsRAMAddress(u32 address, bool translate)
{
bool performTranslation = UReg_MSR(MSR).DR;
int segment = address >> 28;
if (performTranslation)
if (translate)
{
auto translate_address = TranslateAddress<FLAG_NO_EXCEPTION>(address);
auto translate_address = TranslateAddress<flag>(address);
if (!translate_address.Success())
return false;
address = translate_address.address;
segment = address >> 28;
}
u32 segment = address >> 28;
if (segment == 0x0 && (address & 0x0FFFFFFF) < Memory::REALRAM_SIZE)
return true;
else if (Memory::m_pEXRAM && segment == 0x1 && (address & 0x0FFFFFFF) < Memory::EXRAM_SIZE)
@ -646,6 +645,17 @@ bool HostIsRAMAddress(u32 address)
return false;
}
bool HostIsRAMAddress(u32 address)
{
return IsRAMAddress<FLAG_NO_EXCEPTION>(address, UReg_MSR(MSR).DR);
}
bool HostIsInstructionRAMAddress(u32 address)
{
// Instructions are always 32bit aligned.
return !(address & 3) && IsRAMAddress<FLAG_OPCODE_NO_EXCEPTION>(address, UReg_MSR(MSR).IR);
}
void DMA_LCToMemory(const u32 memAddr, const u32 cacheAddr, const u32 numBlocks)
{
// TODO: It's not completely clear this is the right spot for this code;
@ -1240,7 +1250,7 @@ void IBATUpdated()
template <const XCheckTLBFlag flag>
static TranslateAddressResult TranslateAddress(const u32 address)
{
u32 bat_result = (flag == FLAG_OPCODE ? ibat_table : dbat_table)[address >> BAT_INDEX_SHIFT];
u32 bat_result = (IsOpcodeFlag(flag) ? ibat_table : dbat_table)[address >> BAT_INDEX_SHIFT];
if (bat_result & 1)
{
u32 result_addr = (bat_result & ~3) | (address & 0x0001FFFF);

View File

@ -220,6 +220,8 @@ void HostWrite_U64(const u64 var, const u32 address);
// Returns whether a read or write to the given address will resolve to a RAM
// access given the current CPU state.
bool HostIsRAMAddress(const u32 address);
// Same as HostIsRAMAddress, but uses IBAT instead of DBAT.
bool HostIsInstructionRAMAddress(u32 address);
std::string HostGetString(u32 em_address, size_t size = 0);