diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 3280f99e9..ba2e2bd1a 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -151,13 +151,16 @@ ResultCode VMManager::ChangeMemoryState(VAddr target, u32 size, MemoryState expe } CASCADE_RESULT(auto vma, CarveVMARange(target, size)); - ASSERT(vma->second.size == size); - vma->second.permissions = new_perms; - vma->second.meminfo_state = new_state; - UpdatePageTableForVMA(vma->second); - - MergeAdjacent(vma); + const VMAIter end = vma_map.end(); + // The comparison against the end of the range must be done using addresses since VMAs can be + // merged during this process, causing invalidation of the iterators. + while (vma != end && vma->second.base < target_end) { + vma->second.permissions = new_perms; + vma->second.meminfo_state = new_state; + UpdatePageTableForVMA(vma->second); + vma = std::next(MergeAdjacent(vma)); + } return RESULT_SUCCESS; } diff --git a/src/core/hle/service/ldr_ro/ldr_ro.cpp b/src/core/hle/service/ldr_ro/ldr_ro.cpp index 274d36ed5..a435d5e58 100644 --- a/src/core/hle/service/ldr_ro/ldr_ro.cpp +++ b/src/core/hle/service/ldr_ro/ldr_ro.cpp @@ -41,10 +41,17 @@ static const ResultCode ERROR_NOT_LOADED = // 0xD8A12C0D static bool VerifyBufferState(Kernel::Process& process, VAddr buffer_ptr, u32 size) { auto vma = process.vm_manager.FindVMA(buffer_ptr); - return vma != process.vm_manager.vma_map.end() && - vma->second.base + vma->second.size >= buffer_ptr + size && - vma->second.permissions == Kernel::VMAPermission::ReadWrite && - vma->second.meminfo_state == Kernel::MemoryState::Private; + while (vma != process.vm_manager.vma_map.end()) { + if (vma->second.permissions != Kernel::VMAPermission::ReadWrite || + vma->second.meminfo_state != Kernel::MemoryState::Private) { + return false; + } + if (vma->second.base + vma->second.size >= buffer_ptr + size) { + return true; + } + vma = std::next(vma); + } + return false; } void RO::Initialize(Kernel::HLERequestContext& ctx) {