From 1905d22a9a781c463c0e63d6085b7986928ed19b Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Thu, 12 Dec 2019 01:16:05 +1000 Subject: [PATCH] CPU/Recompiler/AArch64: Fix potential stack corruption in function calls --- .../cpu_recompiler_code_generator_aarch64.cpp | 40 ++++++++++++++----- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/core/cpu_recompiler_code_generator_aarch64.cpp b/src/core/cpu_recompiler_code_generator_aarch64.cpp index 3fd43ca2d..f2954493c 100644 --- a/src/core/cpu_recompiler_code_generator_aarch64.cpp +++ b/src/core/cpu_recompiler_code_generator_aarch64.cpp @@ -918,18 +918,22 @@ void CodeGenerator::EmitFunctionCallPtr(Value* return_value, const void* ptr) if (return_value) return_value->Discard(); + // must be allocated before the stack push + Value temp = m_register_cache.AllocateScratch(RegSize_64); + // shadow space allocate const u32 adjust_size = PrepareStackForCall(); // actually call the function - Value temp = m_register_cache.AllocateScratch(RegSize_64); m_emit->Mov(GetHostReg64(temp), reinterpret_cast(ptr)); m_emit->Blr(GetHostReg64(temp)); - temp.ReleaseAndClear(); // shadow space release RestoreStackAfterCall(adjust_size); + // must happen after the stack push + temp.ReleaseAndClear(); + // copy out return value if requested if (return_value) { @@ -943,6 +947,9 @@ void CodeGenerator::EmitFunctionCallPtr(Value* return_value, const void* ptr, co if (return_value) return_value->Discard(); + // must be allocated before the stack push + Value temp = m_register_cache.AllocateScratch(RegSize_64); + // shadow space allocate const u32 adjust_size = PrepareStackForCall(); @@ -950,14 +957,15 @@ void CodeGenerator::EmitFunctionCallPtr(Value* return_value, const void* ptr, co EmitCopyValue(RARG1, arg1); // actually call the function - Value temp = m_register_cache.AllocateScratch(RegSize_64); m_emit->Mov(GetHostReg64(temp), reinterpret_cast(ptr)); m_emit->Blr(GetHostReg64(temp)); - temp.ReleaseAndClear(); // shadow space release RestoreStackAfterCall(adjust_size); + // must happen after the stack push + temp.ReleaseAndClear(); + // copy out return value if requested if (return_value) { @@ -971,6 +979,9 @@ void CodeGenerator::EmitFunctionCallPtr(Value* return_value, const void* ptr, co if (return_value) return_value->Discard(); + // must be allocated before the stack push + Value temp = m_register_cache.AllocateScratch(RegSize_64); + // shadow space allocate const u32 adjust_size = PrepareStackForCall(); @@ -979,14 +990,15 @@ void CodeGenerator::EmitFunctionCallPtr(Value* return_value, const void* ptr, co EmitCopyValue(RARG2, arg2); // actually call the function - Value temp = m_register_cache.AllocateScratch(RegSize_64); m_emit->Mov(GetHostReg64(temp), reinterpret_cast(ptr)); m_emit->Blr(GetHostReg64(temp)); - temp.ReleaseAndClear(); // shadow space release RestoreStackAfterCall(adjust_size); + // must happen after the stack push + temp.ReleaseAndClear(); + // copy out return value if requested if (return_value) { @@ -1001,6 +1013,9 @@ void CodeGenerator::EmitFunctionCallPtr(Value* return_value, const void* ptr, co if (return_value) 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 const u32 adjust_size = PrepareStackForCall(); @@ -1010,14 +1025,15 @@ void CodeGenerator::EmitFunctionCallPtr(Value* return_value, const void* ptr, co EmitCopyValue(RARG3, arg3); // actually call the function - Value temp = m_register_cache.AllocateScratch(RegSize_64); m_emit->Mov(GetHostReg64(temp), reinterpret_cast(ptr)); m_emit->Blr(GetHostReg64(temp)); - temp.ReleaseAndClear(); // shadow space release RestoreStackAfterCall(adjust_size); + // must happen after the stack push + temp.ReleaseAndClear(); + // copy out return value if requested if (return_value) { @@ -1032,6 +1048,9 @@ void CodeGenerator::EmitFunctionCallPtr(Value* return_value, const void* ptr, co if (return_value) return_value->Discard(); + // must be allocated before the stack push + Value temp = m_register_cache.AllocateScratch(RegSize_64); + // shadow space allocate const u32 adjust_size = PrepareStackForCall(); @@ -1042,14 +1061,15 @@ void CodeGenerator::EmitFunctionCallPtr(Value* return_value, const void* ptr, co EmitCopyValue(RARG4, arg4); // actually call the function - Value temp = m_register_cache.AllocateScratch(RegSize_64); m_emit->Mov(GetHostReg64(temp), reinterpret_cast(ptr)); m_emit->Blr(GetHostReg64(temp)); - temp.ReleaseAndClear(); // shadow space release RestoreStackAfterCall(adjust_size); + // must happen after the stack push + temp.ReleaseAndClear(); + // copy out return value if requested if (return_value) {