From e2bc0171122b780696ffa7717f15b1714da0e04e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 10 Aug 2026 11:17:45 +0200 Subject: [PATCH] More removals of Read_U32 --- Core/HLE/sceKernelMutex.cpp | 28 +++------ Core/HLE/sceKernelThread.cpp | 108 +++++++++++++++++++---------------- 2 files changed, 66 insertions(+), 70 deletions(-) diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index c1f937fd5e..92b986d545 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -426,14 +426,12 @@ static bool __KernelUnlockMutex(PSPMutex *mutex, u32 &error) { return wokeThreads; } -void __KernelMutexTimeout(u64 userdata, int cyclesLate) -{ +void __KernelMutexTimeout(u64 userdata, int cyclesLate) { SceUID threadID = (SceUID)userdata; HLEKernel::WaitExecTimeout(threadID); } -void __KernelMutexThreadEnd(SceUID threadID) -{ +void __KernelMutexThreadEnd(SceUID threadID) { u32 error; // If it was waiting on the mutex, it should finish now. @@ -480,8 +478,7 @@ static void __KernelWaitMutex(PSPMutex *mutex, u32 timeoutPtr) { CoreTiming::ScheduleEvent(usToCycles(micro), mutexWaitTimer, __KernelGetCurThread()); } -int sceKernelCancelMutex(SceUID uid, int count, u32 numWaitThreadsPtr) -{ +int sceKernelCancelMutex(SceUID uid, int count, u32 numWaitThreadsPtr) { u32 error; PSPMutex *mutex = kernelObjects.Get(uid, error); if (!mutex) { @@ -527,7 +524,6 @@ int sceKernelCancelMutex(SceUID uid, int count, u32 numWaitThreadsPtr) } } -// int sceKernelLockMutex(SceUID id, int count, int *timeout) int sceKernelLockMutex(SceUID id, int count, u32 timeoutPtr) { // Tekken 6 hack: Let's avoid the unnecessary logspam. It does this on hardware too. // This ID is always invalid. @@ -567,7 +563,6 @@ int sceKernelLockMutex(SceUID id, int count, u32 timeoutPtr) { return hleLogDebug(Log::sceKernel, 0); } -// int sceKernelLockMutexCB(SceUID id, int count, int *timeout) int sceKernelLockMutexCB(SceUID id, int count, u32 timeoutPtr) { if (timeoutPtr != 0) { if (!Memory::IsValid4AlignedAddress(timeoutPtr)) { @@ -611,7 +606,6 @@ int sceKernelLockMutexCB(SceUID id, int count, u32 timeoutPtr) { } } -// int sceKernelTryLockMutex(SceUID id, int count) int sceKernelTryLockMutex(SceUID id, int count) { u32 error; PSPMutex *mutex = kernelObjects.Get(id, error); @@ -624,9 +618,7 @@ int sceKernelTryLockMutex(SceUID id, int count) { return hleLogDebug(Log::sceKernel, SCE_MUTEX_ERROR_TRYLOCK_FAILED); } -// int sceKernelUnlockMutex(SceUID id, int count) -int sceKernelUnlockMutex(SceUID id, int count) -{ +int sceKernelUnlockMutex(SceUID id, int count) { // Tekken 6 hack: Let's avoid the unnecessary logspam. It does this on hardware too. // This ID is always invalid. if (id == 0x80020001) { @@ -733,8 +725,7 @@ int sceKernelCreateLwMutex(u32 workareaPtr, const char *name, u32 attr, int init } template -bool __KernelUnlockLwMutexForThread(LwMutex *mutex, T workarea, SceUID threadID, u32 &error, int result) -{ +bool __KernelUnlockLwMutexForThread(LwMutex *mutex, T workarea, SceUID threadID, u32 &error, int result) { if (!HLEKernel::VerifyWait(threadID, WAITTYPE_LWMUTEX, mutex->GetUID())) return false; @@ -784,8 +775,7 @@ int sceKernelDeleteLwMutex(u32 workareaPtr) { } } -static bool __KernelLockLwMutex(NativeLwMutexWorkarea *workarea, int count, u32 &error) -{ +static bool __KernelLockLwMutex(NativeLwMutexWorkarea *workarea, int count, u32 &error) { if (!error) { if (count <= 0) @@ -836,11 +826,9 @@ static bool __KernelLockLwMutex(NativeLwMutexWorkarea *workarea, int count, u32 } template -bool __KernelUnlockLwMutex(T workarea, u32 &error) -{ +bool __KernelUnlockLwMutex(T workarea, u32 &error) { LwMutex *mutex = kernelObjects.Get(workarea->uid, error); - if (error) - { + if (error) { workarea->lockThread = 0; return false; } diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 567377b624..f005739e72 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -28,6 +28,7 @@ #include "Common/Serialize/SerializeFuncs.h" #include "Common/Serialize/SerializeList.h" #include "Common/Serialize/SerializeMap.h" +#include "Core/Core.h" #include "Core/HLE/HLE.h" #include "Core/HLE/ErrorCodes.h" #include "Core/HLE/HLETables.h" @@ -357,8 +358,7 @@ bool PSPThread::AllocateStack(u32 &stackSize) { bool fromTop = (nt.attr & PSP_THREAD_ATTR_LOW_STACK) == 0; currentStack.start = StackAllocator().Alloc(stackSize, fromTop, StringFromFormat("stack/%s", nt.name).c_str()); - if (currentStack.start == (u32)-1) - { + if (currentStack.start == (u32)-1) { currentStack.start = 0; nt.initialStack = 0; ERROR_LOG(Log::sceKernel, "Failed to allocate stack for thread"); @@ -1155,8 +1155,7 @@ SceUID __KernelGetCurrentCallbackID(SceUID threadID, u32 &error) { } } -u32 sceKernelReferThreadStatus(u32 threadID, u32 statusPtr) -{ +u32 sceKernelReferThreadStatus(u32 threadID, u32 statusPtr) { static const u32 THREADINFO_SIZE = 104; static const u32 THREADINFO_SIZE_AFTER_260 = 108; @@ -1171,7 +1170,12 @@ u32 sceKernelReferThreadStatus(u32 threadID, u32 statusPtr) return hleLogError(Log::sceKernel, error, "bad thread"); } - u32 wantedSize = Memory::Read_U32(statusPtr); + if (!Memory::IsValid4AlignedAddress(statusPtr)) { + Core_MemoryExceptionHLE(currentMIPS, statusPtr, 0, MemoryExceptionType::HLE_READ); + return hleNoLog(0); + } + + u32 wantedSize = Memory::ReadUnchecked_U32(statusPtr); if (sceKernelGetCompiledSdkVersion() > 0x02060010) { if (wantedSize > THREADINFO_SIZE_AFTER_260) { @@ -1199,8 +1203,7 @@ u32 sceKernelReferThreadStatus(u32 threadID, u32 statusPtr) } // Thanks JPCSP -u32 sceKernelReferThreadRunStatus(u32 threadID, u32 statusPtr) -{ +u32 sceKernelReferThreadRunStatus(u32 threadID, u32 statusPtr) { if (threadID == 0) threadID = __KernelGetCurThread(); @@ -1210,8 +1213,10 @@ u32 sceKernelReferThreadRunStatus(u32 threadID, u32 statusPtr) return hleLogError(Log::sceKernel, error, "bad thread"); } - if (!Memory::IsValidAddress(statusPtr)) + if (!Memory::IsValidRange(statusPtr, sizeof(SceKernelThreadRunStatus))) { + // Raise exception? return hleLogError(Log::sceKernel, -1); + } auto runStatus = PSPPointer::Create(statusPtr); @@ -2574,7 +2579,7 @@ int sceKernelWaitThreadEnd(SceUID threadID, u32 timeoutPtr) { if (t->nt.status != THREADSTATUS_DORMANT) { if (Memory::IsValidAddress(timeoutPtr)) - __KernelScheduleThreadEndTimeout(currentThread, threadID, Memory::Read_U32(timeoutPtr)); + __KernelScheduleThreadEndTimeout(currentThread, threadID, Memory::ReadUnchecked_U32(timeoutPtr)); if (std::find(t->waitingThreads.begin(), t->waitingThreads.end(), currentThread) == t->waitingThreads.end()) t->waitingThreads.push_back(currentThread); __KernelWaitCurThread(WAITTYPE_THREADEND, threadID, 0, timeoutPtr, false, "thread wait end"); @@ -2601,7 +2606,7 @@ int sceKernelWaitThreadEndCB(SceUID threadID, u32 timeoutPtr) { if (t->nt.status != THREADSTATUS_DORMANT) { if (Memory::IsValidAddress(timeoutPtr)) - __KernelScheduleThreadEndTimeout(currentThread, threadID, Memory::Read_U32(timeoutPtr)); + __KernelScheduleThreadEndTimeout(currentThread, threadID, Memory::ReadUnchecked_U32(timeoutPtr)); if (std::find(t->waitingThreads.begin(), t->waitingThreads.end(), currentThread) == t->waitingThreads.end()) t->waitingThreads.push_back(currentThread); __KernelWaitCurThread(WAITTYPE_THREADEND, threadID, 0, timeoutPtr, true, "thread wait end"); @@ -2828,25 +2833,28 @@ u32 sceKernelExtendThreadStack(u32 size, u32 entryAddr, u32 entryParameter) return hleLogDebug(Log::sceKernel, 0); } -void __KernelReturnFromExtendStack() -{ +void __KernelReturnFromExtendStack() { hleSkipDeadbeef(); PSPThread *thread = __GetCurrentThread(); - if (!thread) - { + if (!thread) { ERROR_LOG_REPORT(Log::sceKernel, "__KernelReturnFromExtendStack() - not on a thread?"); hleNoLogVoid(); return; } - // Grab the saved regs at the top of the stack. - u32 restoreRA = Memory::Read_U32(thread->currentStack.end - 4); - u32 restoreSP = Memory::Read_U32(thread->currentStack.end - 8); - u32 restorePC = Memory::Read_U32(thread->currentStack.end - 12); + if (!Memory::IsValid4AlignedRange(thread->currentStack.end - 12, 12)) { + Core_MemoryExceptionHLE(currentMIPS, thread->currentStack.end, 12, MemoryExceptionType::HLE_READ); + hleNoLogVoid(); + return; + } - if (!thread->PopExtendedStack()) - { + // Grab the saved regs at the top of the stack. + u32 restoreRA = Memory::ReadUnchecked_U32(thread->currentStack.end - 4); + u32 restoreSP = Memory::ReadUnchecked_U32(thread->currentStack.end - 8); + u32 restorePC = Memory::ReadUnchecked_U32(thread->currentStack.end - 12); + + if (!thread->PopExtendedStack()) { ERROR_LOG_REPORT(Log::sceKernel, "__KernelReturnFromExtendStack() - no stack to restore?"); return; } @@ -2944,16 +2952,15 @@ void __KernelSwitchContext(PSPThread *target, const char *reason) { __KernelChangeReadyState(cur, oldUID, true); } - if (target) - { + if (target) { __SetCurrentThread(target, target->GetUID(), target->nt.name); __KernelChangeReadyState(target, currentThread, false); target->nt.status = (target->nt.status | THREADSTATUS_RUNNING) & ~THREADSTATUS_READY; __KernelLoadContext(&target->context, (target->nt.attr & PSP_THREAD_ATTR_VFPU) != 0); - } - else + } else { __SetCurrentThread(NULL, 0, NULL); + } const bool fromIdle = oldUID == threadIdleID[0] || oldUID == threadIdleID[1]; const bool toIdle = currentThread == threadIdleID[0] || currentThread == threadIdleID[1]; @@ -3187,14 +3194,21 @@ void __KernelReturnFromMipsCall() { call->doAfter = nullptr; } - u32 &sp = currentMIPS->r[MIPS_REG_SP]; - for (int i = MIPS_REG_A0; i <= MIPS_REG_T7; ++i) { - currentMIPS->r[i] = Memory::Read_U32(sp + i * 4); + u32 sp = currentMIPS->r[MIPS_REG_SP]; + if (!Memory::IsValid4AlignedRange(sp, 32 * 4)) { + // We're really screwed. + Core_MemoryExceptionHLE(currentMIPS, sp, 4, MemoryExceptionType::HLE_READ); + return hleNoLogVoid(); } - currentMIPS->r[MIPS_REG_T8] = Memory::Read_U32(sp + MIPS_REG_T8 * 4); - currentMIPS->r[MIPS_REG_T9] = Memory::Read_U32(sp + MIPS_REG_T9 * 4); - currentMIPS->r[MIPS_REG_RA] = Memory::Read_U32(sp + MIPS_REG_RA * 4); - sp += 32 * 4; + + for (int i = MIPS_REG_A0; i <= MIPS_REG_T7; ++i) { + currentMIPS->r[i] = Memory::ReadUnchecked_U32(sp + i * 4); + } + currentMIPS->r[MIPS_REG_T8] = Memory::ReadUnchecked_U32(sp + MIPS_REG_T8 * 4); + currentMIPS->r[MIPS_REG_T9] = Memory::ReadUnchecked_U32(sp + MIPS_REG_T9 * 4); + currentMIPS->r[MIPS_REG_RA] = Memory::ReadUnchecked_U32(sp + MIPS_REG_RA * 4); + // Increment SP. + currentMIPS->r[MIPS_REG_SP] += 32 * 4; KernelValidateThreadTarget(call->savedPc); @@ -3210,15 +3224,11 @@ void __KernelReturnFromMipsCall() { } currentCallbackThreadID = 0; - if (cur->nt.waitType != WAITTYPE_NONE) - { - if (call->cbId > 0) - { - if (waitTypeFuncs[cur->nt.waitType].endFunc != NULL) - waitTypeFuncs[cur->nt.waitType].endFunc(cur->GetUID(), cur->currentCallbackId); - else - ERROR_LOG_REPORT(Log::HLE, "Missing begin/restore funcs for wait type %d", cur->nt.waitType); - } + if (cur->nt.waitType != WAITTYPE_NONE && call->cbId > 0) { + if (waitTypeFuncs[cur->nt.waitType].endFunc != NULL) + waitTypeFuncs[cur->nt.waitType].endFunc(cur->GetUID(), cur->currentCallbackId); + else + ERROR_LOG_REPORT(Log::HLE, "Missing begin/restore funcs for wait type %d", cur->nt.waitType); } // yeah! back in the real world, let's keep going. Should we process more callbacks? @@ -3568,8 +3578,7 @@ bool __KernelIsExitCallbackPending() { } // Update the exit callback status? -int LoadExecForUser_362A956B() -{ +int LoadExecForUser_362A956B() { WARN_LOG_REPORT(Log::sceKernel, "LoadExecForUser_362A956B()"); u32 error; PSPCallback *cb = kernelObjects.Get(registeredExitCbId, error); @@ -3577,24 +3586,23 @@ int LoadExecForUser_362A956B() return hleLogWarning(Log::sceKernel, SCE_KERNEL_ERROR_UNKNOWN_CBID, "registeredExitCbId not found 0x%x", registeredExitCbId); } int cbArg = cb->nc.commonArgument; - if (!Memory::IsValidAddress(cbArg)) { + if (!Memory::IsValidRange(cbArg - 8, 8)) { return hleLogWarning(Log::sceKernel, SCE_KERNEL_ERROR_ILLEGAL_ADDR, "invalid address for cbArg (0x%08X)", cbArg); } - u32 unknown1 = Memory::Read_U32(cbArg - 8); + const u32 unknown1 = Memory::ReadUnchecked_U32(cbArg - 8); if (unknown1 >= 4) { return hleLogWarning(Log::sceKernel, SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, "invalid value unknown1 (0x%08X)", unknown1); } - u32 parameterArea = Memory::Read_U32(cbArg - 4); - if (!Memory::IsValidAddress(parameterArea)) { + const u32 parameterArea = Memory::ReadUnchecked_U32(cbArg - 4); + if (!Memory::IsValid4AlignedRange(parameterArea, 12)) { return hleLogWarning(Log::sceKernel, SCE_KERNEL_ERROR_ILLEGAL_ADDR, "invalid address for parameterArea on userMemory (0x%08X)", parameterArea); } - - u32 size = Memory::Read_U32(parameterArea); + const u32 size = Memory::ReadUnchecked_U32(parameterArea); if (size < 12) { return hleLogWarning(Log::sceKernel, SCE_KERNEL_ERROR_ILLEGAL_SIZE, "invalid parameterArea size %d", size); } - Memory::Write_U32(0, parameterArea + 4); - Memory::Write_U32(-1, parameterArea + 8); + Memory::WriteUnchecked_U32(0, parameterArea + 4); + Memory::WriteUnchecked_U32(-1, parameterArea + 8); return hleLogDebug(Log::sceKernel, 0); }