mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-09-04 03:35:19 +02:00
MemoryUtil: fall back to far memory when the near reservation fails
The x86-64 path searched for free memory near the code, and if it found some, committed to it - if that VirtualAlloc failed, ptr was left null and we returned null, never reaching the else branch that exists precisely to say "can still run, thanks to RipAccessible". Finding a free region isn't the same as being able to reserve it. VirtualAlloc rounds a non-null lpAddress down to the 64K allocation granularity while SearchForFreeMem only guarantees page alignment, so the rounded-down base can land back inside a committed region; a concurrent allocation between the VirtualQuery and the VirtualAlloc does it too. Callers don't check the result - AllocCodeSpace stores it unchecked and the emitters write from there - so this turned into a wild write rather than a clean JIT-unavailable fallback.
This commit is contained in:
@@ -145,8 +145,17 @@ void *AllocateExecutableMemory(size_t size) {
|
||||
#endif
|
||||
if (ptr) {
|
||||
ptr = VirtualAlloc(ptr, aligned_size, MEM_RESERVE | MEM_COMMIT, prot);
|
||||
if (!ptr) {
|
||||
// Finding a free region isn't the same as being able to reserve it: VirtualAlloc
|
||||
// rounds a non-null address down to the 64K allocation granularity, and
|
||||
// SearchForFreeMem only returns page alignment, so the rounded-down base can land
|
||||
// back inside something committed. Another thread allocating in between does it too.
|
||||
WARN_LOG(Log::Common, "Could not reserve the nearby executable memory found for jit. Proceeding with far memory.");
|
||||
}
|
||||
} else {
|
||||
WARN_LOG(Log::Common, "Unable to find nearby executable memory for jit. Proceeding with far memory.");
|
||||
}
|
||||
if (!ptr) {
|
||||
// Can still run, thanks to "RipAccessible".
|
||||
ptr = VirtualAlloc(nullptr, aligned_size, MEM_RESERVE | MEM_COMMIT, prot);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user