Skip to content

Commit

Permalink
Add thread check to AchievementManager MemoryPeeker
Browse files Browse the repository at this point in the history
rc_client calls the provided memory peeker asynchronously in the callback for starting a session, to validate/invalidate the memory used for achievements. Dolphin cannot access memory from any thread but host or CPU so this access has a small chance of being invalid. This adds a verification to that method to ensure that memory is only being accessed on the correct threads but that the response when this isn't the case is what rc_client expects.
  • Loading branch information
LillyJadeKatrin committed Jun 19, 2024
1 parent a0d8c10 commit e9b6fc7
Showing 1 changed file with 11 additions and 0 deletions.
11 changes: 11 additions & 0 deletions Source/Core/Core/AchievementManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "Common/WorkQueueThread.h"
#include "Core/Config/AchievementSettings.h"
#include "Core/Core.h"
#include "Core/HW/Memmap.h"
#include "Core/PowerPC/MMU.h"
#include "Core/System.h"
#include "DiscIO/Blob.h"
Expand Down Expand Up @@ -919,6 +920,16 @@ u32 AchievementManager::MemoryPeeker(u32 address, u8* buffer, u32 num_bytes, rc_
if (buffer == nullptr)
return 0u;
auto& system = Core::System::GetInstance();
// If this is called in some other thread, for example a callback, we want to make sure we return
// how many bytes we *could* read even if we can't, because rc_client will deactivate achievements
// and leaderboards as "unsupported" if the memory access is invalid.
if (!(Core::IsHostThread() || Core::IsCPUThread()))
{
u32 ram_size = system.GetMemory().GetRamSizeReal();
if (address >= ram_size)
return 0;
return std::min(ram_size - address, num_bytes);
}
Core::CPUThreadGuard threadguard(system);
for (u32 num_read = 0; num_read < num_bytes; num_read++)
{
Expand Down

0 comments on commit e9b6fc7

Please sign in to comment.