CPU/Recompiler/AArch64: Fix potential stack corruption in function calls

This commit is contained in:
Connor McLaughlin 2019-12-12 01:16:05 +10:00
parent 18066239b7
commit 1905d22a9a
1 changed files with 30 additions and 10 deletions

View File

@ -918,18 +918,22 @@ void CodeGenerator::EmitFunctionCallPtr(Value* return_value, const void* ptr)
if (return_value) if (return_value)
return_value->Discard(); return_value->Discard();
// must be allocated before the stack push
Value temp = m_register_cache.AllocateScratch(RegSize_64);
// shadow space allocate // shadow space allocate
const u32 adjust_size = PrepareStackForCall(); const u32 adjust_size = PrepareStackForCall();
// actually call the function // actually call the function
Value temp = m_register_cache.AllocateScratch(RegSize_64);
m_emit->Mov(GetHostReg64(temp), reinterpret_cast<uintptr_t>(ptr)); m_emit->Mov(GetHostReg64(temp), reinterpret_cast<uintptr_t>(ptr));
m_emit->Blr(GetHostReg64(temp)); m_emit->Blr(GetHostReg64(temp));
temp.ReleaseAndClear();
// shadow space release // shadow space release
RestoreStackAfterCall(adjust_size); RestoreStackAfterCall(adjust_size);
// must happen after the stack push
temp.ReleaseAndClear();
// copy out return value if requested // copy out return value if requested
if (return_value) if (return_value)
{ {
@ -943,6 +947,9 @@ void CodeGenerator::EmitFunctionCallPtr(Value* return_value, const void* ptr, co
if (return_value) if (return_value)
return_value->Discard(); return_value->Discard();
// must be allocated before the stack push
Value temp = m_register_cache.AllocateScratch(RegSize_64);
// shadow space allocate // shadow space allocate
const u32 adjust_size = PrepareStackForCall(); const u32 adjust_size = PrepareStackForCall();
@ -950,14 +957,15 @@ void CodeGenerator::EmitFunctionCallPtr(Value* return_value, const void* ptr, co
EmitCopyValue(RARG1, arg1); EmitCopyValue(RARG1, arg1);
// actually call the function // actually call the function
Value temp = m_register_cache.AllocateScratch(RegSize_64);
m_emit->Mov(GetHostReg64(temp), reinterpret_cast<uintptr_t>(ptr)); m_emit->Mov(GetHostReg64(temp), reinterpret_cast<uintptr_t>(ptr));
m_emit->Blr(GetHostReg64(temp)); m_emit->Blr(GetHostReg64(temp));
temp.ReleaseAndClear();
// shadow space release // shadow space release
RestoreStackAfterCall(adjust_size); RestoreStackAfterCall(adjust_size);
// must happen after the stack push
temp.ReleaseAndClear();
// copy out return value if requested // copy out return value if requested
if (return_value) if (return_value)
{ {
@ -971,6 +979,9 @@ void CodeGenerator::EmitFunctionCallPtr(Value* return_value, const void* ptr, co
if (return_value) if (return_value)
return_value->Discard(); return_value->Discard();
// must be allocated before the stack push
Value temp = m_register_cache.AllocateScratch(RegSize_64);
// shadow space allocate // shadow space allocate
const u32 adjust_size = PrepareStackForCall(); const u32 adjust_size = PrepareStackForCall();
@ -979,14 +990,15 @@ void CodeGenerator::EmitFunctionCallPtr(Value* return_value, const void* ptr, co
EmitCopyValue(RARG2, arg2); EmitCopyValue(RARG2, arg2);
// actually call the function // actually call the function
Value temp = m_register_cache.AllocateScratch(RegSize_64);
m_emit->Mov(GetHostReg64(temp), reinterpret_cast<uintptr_t>(ptr)); m_emit->Mov(GetHostReg64(temp), reinterpret_cast<uintptr_t>(ptr));
m_emit->Blr(GetHostReg64(temp)); m_emit->Blr(GetHostReg64(temp));
temp.ReleaseAndClear();
// shadow space release // shadow space release
RestoreStackAfterCall(adjust_size); RestoreStackAfterCall(adjust_size);
// must happen after the stack push
temp.ReleaseAndClear();
// copy out return value if requested // copy out return value if requested
if (return_value) if (return_value)
{ {
@ -1001,6 +1013,9 @@ void CodeGenerator::EmitFunctionCallPtr(Value* return_value, const void* ptr, co
if (return_value) if (return_value)
m_register_cache.DiscardHostReg(return_value->GetHostRegister()); m_register_cache.DiscardHostReg(return_value->GetHostRegister());
// must be allocated before the stack push
Value temp = m_register_cache.AllocateScratch(RegSize_64);
// shadow space allocate // shadow space allocate
const u32 adjust_size = PrepareStackForCall(); const u32 adjust_size = PrepareStackForCall();
@ -1010,14 +1025,15 @@ void CodeGenerator::EmitFunctionCallPtr(Value* return_value, const void* ptr, co
EmitCopyValue(RARG3, arg3); EmitCopyValue(RARG3, arg3);
// actually call the function // actually call the function
Value temp = m_register_cache.AllocateScratch(RegSize_64);
m_emit->Mov(GetHostReg64(temp), reinterpret_cast<uintptr_t>(ptr)); m_emit->Mov(GetHostReg64(temp), reinterpret_cast<uintptr_t>(ptr));
m_emit->Blr(GetHostReg64(temp)); m_emit->Blr(GetHostReg64(temp));
temp.ReleaseAndClear();
// shadow space release // shadow space release
RestoreStackAfterCall(adjust_size); RestoreStackAfterCall(adjust_size);
// must happen after the stack push
temp.ReleaseAndClear();
// copy out return value if requested // copy out return value if requested
if (return_value) if (return_value)
{ {
@ -1032,6 +1048,9 @@ void CodeGenerator::EmitFunctionCallPtr(Value* return_value, const void* ptr, co
if (return_value) if (return_value)
return_value->Discard(); return_value->Discard();
// must be allocated before the stack push
Value temp = m_register_cache.AllocateScratch(RegSize_64);
// shadow space allocate // shadow space allocate
const u32 adjust_size = PrepareStackForCall(); const u32 adjust_size = PrepareStackForCall();
@ -1042,14 +1061,15 @@ void CodeGenerator::EmitFunctionCallPtr(Value* return_value, const void* ptr, co
EmitCopyValue(RARG4, arg4); EmitCopyValue(RARG4, arg4);
// actually call the function // actually call the function
Value temp = m_register_cache.AllocateScratch(RegSize_64);
m_emit->Mov(GetHostReg64(temp), reinterpret_cast<uintptr_t>(ptr)); m_emit->Mov(GetHostReg64(temp), reinterpret_cast<uintptr_t>(ptr));
m_emit->Blr(GetHostReg64(temp)); m_emit->Blr(GetHostReg64(temp));
temp.ReleaseAndClear();
// shadow space release // shadow space release
RestoreStackAfterCall(adjust_size); RestoreStackAfterCall(adjust_size);
// must happen after the stack push
temp.ReleaseAndClear();
// copy out return value if requested // copy out return value if requested
if (return_value) if (return_value)
{ {