From 3c81d6b121e2b8dc1053529f740650e7d7fa9d54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 11 Aug 2026 09:34:55 +0200 Subject: [PATCH] More manual Read_U32 cleanup Buildfix --- Core/CMakeLists.txt | 1 + Core/Core.vcxproj | 1 + Core/Core.vcxproj.filters | 3 ++ Core/Debugger/Breakpoints.cpp | 6 +++- Core/Dialog/PSPNetconfDialog.cpp | 36 +++++++++++------------ Core/Dialog/PSPNpSigninDialog.cpp | 11 ++++---- Core/Dialog/PSPSaveDialog.cpp | 12 +++++--- Core/HLE/HLE.cpp | 7 ++++- Core/HLE/HLEUtil.h | 17 +++++++++++ Core/HLE/sceAtrac.cpp | 3 +- Core/HLE/sceKernelMsgPipe.cpp | 47 ++++++++++++++++--------------- Core/HLE/sceKernelSemaphore.cpp | 15 ++++++++-- Core/HLE/sceKernelVTimer.cpp | 8 +++--- Core/HLE/sceMp3.cpp | 2 +- Core/HLE/sceNetAdhoc.cpp | 8 ++++-- Core/HLE/sceNetInet.cpp | 2 +- Core/HLE/sceNp.cpp | 14 ++++----- Core/HLE/sceP3da.cpp | 25 ++++++++-------- Core/HLE/sceSas.cpp | 8 +++++- Core/HW/SasAudio.cpp | 1 + 20 files changed, 141 insertions(+), 86 deletions(-) create mode 100644 Core/HLE/HLEUtil.h diff --git a/Core/CMakeLists.txt b/Core/CMakeLists.txt index 8297f9192f..ea436b1054 100644 --- a/Core/CMakeLists.txt +++ b/Core/CMakeLists.txt @@ -385,6 +385,7 @@ add_library(Core STATIC HLE/FunctionWrappers.h HLE/HLE.cpp HLE/HLE.h + HLE/HLEUtil.h HLE/ReplaceTables.cpp HLE/ReplaceTables.h HLE/HLEHelperThread.cpp diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index e65dcf58b8..4897269e84 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -1009,6 +1009,7 @@ + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index bf0fbd6dc7..9cc881974b 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -2262,6 +2262,9 @@ Core + + HLE + diff --git a/Core/Debugger/Breakpoints.cpp b/Core/Debugger/Breakpoints.cpp index 2fd7f1111e..58ef387047 100644 --- a/Core/Debugger/Breakpoints.cpp +++ b/Core/Debugger/Breakpoints.cpp @@ -660,7 +660,11 @@ bool BreakpointManager::EvaluateLogFormat(MIPSDebugInterface *cpu, const std::st snprintf(resultString, sizeof(resultString), "%f", expResult.f); break; case 'p': - snprintf(resultString, sizeof(resultString), "%08x[%08x]", expResult.u, Memory::IsValidAddress(expResult.u) ? Memory::Read_U32(expResult.u) : 0); + if (Memory::IsValidAddress(expResult.u)) { + snprintf(resultString, sizeof(resultString), "%08x[%08x]", expResult.u, Memory::ReadUnchecked_U32(expResult.u)); + } else { + snprintf(resultString, sizeof(resultString), "%08x[invalid]", expResult.u); + } break; case 's': snprintf(resultString, sizeof(resultString) - 1, "%s", Memory::IsValidAddress(expResult.u) ? Memory::GetCharPointer(expResult.u) : "(invalid)"); diff --git a/Core/Dialog/PSPNetconfDialog.cpp b/Core/Dialog/PSPNetconfDialog.cpp index 9c4248c00a..848daf3f3d 100644 --- a/Core/Dialog/PSPNetconfDialog.cpp +++ b/Core/Dialog/PSPNetconfDialog.cpp @@ -24,6 +24,7 @@ #include "Core/MemMapHelpers.h" #include "Core/Util/PPGeDraw.h" #include "Core/HLE/HLE.h" +#include "Core/HLE/HLEUtil.h" #include "Core/HLE/ErrorCodes.h" #include "Core/HLE/sceKernelMemory.h" #include "Core/HLE/sceCtrl.h" @@ -59,21 +60,15 @@ int PSPNetconfDialog::Init(u32 paramAddr) { if (ReadStatus() != SCE_UTILITY_STATUS_NONE) return SCE_ERROR_UTILITY_INVALID_STATUS; - if (!Memory::IsValid4AlignedRange(paramAddr, sizeof(request))) { - // What to do? - return SCE_KERNEL_ERROR_BAD_ARGUMENT; - } - NOTICE_LOG(Log::sceUtility, "PSPNetConfDialog Init"); jsonReady_ = false; // Kick off a request to the infra-dns.json since we'll need it later. StartInfraJsonDownload(); requestAddr = paramAddr; - const u32 size = Memory::ReadUnchecked_U32(paramAddr); - memset(&request, 0, sizeof(request)); - // Only copy the right size (bounded by the struct) to support different request format - Memory::Memcpy(&request, paramAddr, std::min(size, (u32)sizeof(request))); + if (!ReadVariableSizedStruct(paramAddr, &request.common)) { + return SCE_KERNEL_ERROR_BAD_ARGUMENT; // untested + } ChangeStatusInit(NET_INIT_DELAY_US); @@ -250,22 +245,27 @@ int PSPNetconfDialog::Update(int animSpeed) { if (Memory::IsValidAddress(scanInfosAddr)) userMemory.Free(scanInfosAddr); scanInfosAddr = userMemory.Alloc(structsz, false, "NetconfScanInfo"); - Memory::Write_U32(sizeof(SceNetAdhocctlScanInfoEmu), scanInfosAddr); + // TOOD: What if scanInfosAddr is not valid? + if (Memory::IsValid4AlignedAddress(scanInfosAddr)) { + Memory::WriteUnchecked_U32(sizeof(SceNetAdhocctlScanInfoEmu), scanInfosAddr); + } scanStep = 1; } } else if (scanStep == 1) { - s32 sz = Memory::Read_U32(scanInfosAddr); + s32 sz = Memory::ReadUnchecked_U32(scanInfosAddr); // Get required buffer size if (hleCall(sceNetAdhocctl, int, sceNetAdhocctlGetScanInfo, scanInfosAddr, 0) >= 0) { - s32 reqsz = Memory::Read_U32(scanInfosAddr); + s32 reqsz = Memory::ReadUnchecked_U32(scanInfosAddr); if (reqsz > sz) { sz = reqsz; - if (Memory::IsValidAddress(scanInfosAddr)) - userMemory.Free(scanInfosAddr); + userMemory.Free(scanInfosAddr); u32 structsz = sz + sizeof(s32); scanInfosAddr = userMemory.Alloc(structsz, false, "NetconfScanInfo"); - Memory::Write_U32(sz, scanInfosAddr); + // TOOD: What if scanInfosAddr is not valid? + if (Memory::IsValid4AlignedAddress(scanInfosAddr)) { + Memory::WriteUnchecked_U32(sz, scanInfosAddr); + } } if (reqsz > 0) { if (hleCall(sceNetAdhocctl, int, sceNetAdhocctlGetScanInfo, scanInfosAddr, scanInfosAddr + (u32)sizeof(s32)) >= 0) { @@ -299,7 +299,7 @@ int PSPNetconfDialog::Update(int animSpeed) { connResult = hleCall(sceNetAdhocctl, int, sceNetAdhocctlJoin, scanInfosAddr + (u32)sizeof(s32)); if (connResult >= 0) { // We are done! - if (Memory::IsValidAddress(scanInfosAddr)) + if (Memory::IsValid4AlignedAddress(scanInfosAddr)) userMemory.Free(scanInfosAddr); scanInfosAddr = 0; } @@ -325,7 +325,7 @@ int PSPNetconfDialog::Update(int animSpeed) { } // Let's not leaks any memory - if (Memory::IsValidAddress(scanInfosAddr)) + if (Memory::IsValid4AlignedAddress(scanInfosAddr)) userMemory.Free(scanInfosAddr); scanInfosAddr = 0; } @@ -335,7 +335,7 @@ int PSPNetconfDialog::Update(int animSpeed) { ChangeStatus(SCE_UTILITY_STATUS_FINISHED, NET_SHUTDOWN_DELAY_US); request.common.result = SCE_UTILITY_DIALOG_RESULT_ABORT; // Let's not leaks any memory - if (Memory::IsValidAddress(scanInfosAddr)) + if (Memory::IsValid4AlignedAddress(scanInfosAddr)) userMemory.Free(scanInfosAddr); scanInfosAddr = 0; } diff --git a/Core/Dialog/PSPNpSigninDialog.cpp b/Core/Dialog/PSPNpSigninDialog.cpp index 977cf08dfd..ecc2feb4ca 100644 --- a/Core/Dialog/PSPNpSigninDialog.cpp +++ b/Core/Dialog/PSPNpSigninDialog.cpp @@ -26,6 +26,8 @@ #include "Core/HLE/sceCtrl.h" #include "Core/HLE/sceUtility.h" #include "Core/HLE/sceNp.h" +#include "Core/HLE/HLEUtil.h" +#include "Core/HLE/HLE.h" #include "Core/HLE/ErrorCodes.h" #include "Core/Dialog/PSPNpSigninDialog.h" #include "Common/Data/Encoding/Utf8.h" @@ -42,11 +44,10 @@ int PSPNpSigninDialog::Init(u32 paramAddr) { return SCE_ERROR_UTILITY_INVALID_STATUS; requestAddr = paramAddr; - int size = Memory::Read_U32(paramAddr); - memset(&request, 0, sizeof(request)); - // Only copy the right size to support different request format - Memory::Memcpy(&request, paramAddr, size); - + if (!ReadVariableSizedStruct(paramAddr, &request)) { + return SCE_KERNEL_ERROR_BAD_ARGUMENT; // untested + } + WARN_LOG_REPORT_ONCE(PSPNpSigninDialogInit, Log::sceNet, "NpSignin Init Params: %08x, %08x, %08x, %08x", request.npSigninStatus, request.unknown1, request.unknown2, request.unknown3); ChangeStatusInit(NP_INIT_DELAY_US); diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index 05700dfd8c..3cd79caa14 100755 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -126,8 +126,13 @@ int PSPSaveDialog::Init(int paramAddr) { ioThreadStatus = SAVEIO_NONE; + requestAddr = 0; + if (!Memory::IsValid4AlignedAddress(paramAddr)) { + return SCE_KERNEL_ERROR_BAD_ARGUMENT; // untested + } requestAddr = paramAddr; - int size = Memory::Read_U32(requestAddr); + + int size = Memory::ReadUnchecked_U32(requestAddr); memset(&request, 0, sizeof(request)); // Only copy the right size to support different save request format if (size != SAVEDATA_DIALOG_SIZE_V1 && size != SAVEDATA_DIALOG_SIZE_V2 && size != SAVEDATA_DIALOG_SIZE_V3) { @@ -655,8 +660,7 @@ void PSPSaveDialog::DisplayMessage(std::string_view text, bool hasYesNo) PPGeDrawRect(202.0f, ey, 466.0f, ey + 1.0f, CalcFadedColor(0xFFFFFFFF)); } -int PSPSaveDialog::Update(int animSpeed) -{ +int PSPSaveDialog::Update(int animSpeed) { if (GetStatus() != SCE_UTILITY_STATUS_RUNNING) return SCE_ERROR_UTILITY_INVALID_STATUS; @@ -673,7 +677,7 @@ int PSPSaveDialog::Update(int animSpeed) // The struct may have been updated by the game. This happens in "Where Is My Heart?" // Check if it has changed, reload it. // TODO: Cut down on preloading? This rebuilds the list from scratch. - int size = std::min((u32)sizeof(originalRequest), Memory::Read_U32(requestAddr)); + int size = std::min((u32)sizeof(originalRequest), Memory::ReadUnchecked_U32(requestAddr)); const u8 *updatedRequest = Memory::GetPointerRange(requestAddr, size); if (updatedRequest && memcmp(updatedRequest, &originalRequest, size) != 0) { memset(&request, 0, sizeof(request)); diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index 3404753e62..d898e29deb 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -1032,7 +1032,12 @@ size_t HLEFormatLogArgs(const MIPSState *mips, char *message, size_t sz, const c u32 sp = mips->r[MIPS_REG_SP]; // Goes upward on stack. // NOTE: Currently we only support > 8 for 32-bit integer args. - regval = Memory::Read_U32(sp + (reg - 8) * 4); + if (Memory::IsValid4AlignedAddress(sp)) { + regval = Memory::ReadUnchecked_U32(sp + (reg - 8) * 4); + } else { + // This should basically never happen. + ERROR_LOG(Log::HLE, "Couldn't read sp=%08x for arg %zu", sp, i); + } } switch (argmask[i]) { diff --git a/Core/HLE/HLEUtil.h b/Core/HLE/HLEUtil.h new file mode 100644 index 0000000000..1a590d2498 --- /dev/null +++ b/Core/HLE/HLEUtil.h @@ -0,0 +1,17 @@ +#pragma once +#include +#include "Core/MemMap.h" + +// Used in various places in the PSP OS. +template bool ReadVariableSizedStruct(u32 addr, T *out) { + int size = Memory::ReadUnchecked_U32(addr); + if (!Memory::IsValid4AlignedRange(addr, size)) { + return false; + } + memset(out, 0, sizeof(*out)); + // Only copy the right size to support different struct versions. + // Let's add a debug assert in case we have a struct that is too small for the data. + _dbg_assert_(sizeof(*out) >= size); + Memory::Memcpy(out, addr, std::min(size, (int)sizeof(*out))); + return true; +} diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index abf0f40af2..10becfdb35 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -1110,9 +1110,10 @@ void AtracSasDecodeData(int atracID, u8* outbuf, int *SamplesNum, int *finish) { atrac->DecodeForSas((s16 *)outbuf, SamplesNum, finish); } +// The context pointer is assumed to be valid. int AtracSasBindContextAndGetID(u32 contextAddr) { // Ugly hack, but needed to support both old and new contexts. - int atracID = (int)Memory::Read_U32(contextAddr + 0xfc); + int atracID = (int)Memory::ReadUnchecked_U32(contextAddr + 0xfc); if (atracID < PSP_MAX_ATRAC_IDS && atracContexts[atracID] && atracContexts[atracID]->GetContextVersion() == 1) { // We can assume the old atracID hack was used, and atracID is valid. } else { diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index 37b773e549..9860d11372 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -315,14 +315,13 @@ static void __KernelMsgPipeTimeout(u64 userdata, int cyclesLate) HLEKernel::WaitExecTimeout(threadID); } -static bool __KernelSetMsgPipeTimeout(u32 timeoutPtr) -{ +// Assumes timeout is valid or 0. +static bool __KernelSetMsgPipeTimeout(u32 timeoutPtr) { if (timeoutPtr == 0 || waitTimer == -1) return true; - int micro = (int) Memory::Read_U32(timeoutPtr); - if (micro <= 2) - { + int micro = (int)Memory::ReadUnchecked_U32(timeoutPtr); + if (micro <= 2) { // Don't wait or reschedule, just timeout immediately. return false; } @@ -779,8 +778,8 @@ static int __KernelValidateSendMsgPipe(SceUID uid, u32 sendBufAddr, u32 sendSize return 0; } -static int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, u32 resultAddr, u32 timeoutPtr, bool cbEnabled, bool poll) -{ +// Assumes timeoutPtr is valid or 0. +static int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, u32 resultAddr, u32 timeoutPtr, bool cbEnabled, bool poll) { hleEatCycles(2400); bool needsResched = false; @@ -791,8 +790,7 @@ static int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int wa if (needsResched) hleReSchedule(cbEnabled, "msgpipe data sent"); - if (needsWait) - { + if (needsWait) { if (__KernelSetMsgPipeTimeout(timeoutPtr)) __KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), MSGPIPE_WAIT_VALUE_SEND, timeoutPtr, cbEnabled, "msgpipe send waited"); else @@ -801,8 +799,7 @@ static int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int wa return result; } -int sceKernelSendMsgPipe(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitMode, u32 resultAddr, u32 timeoutPtr) -{ +int sceKernelSendMsgPipe(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitMode, u32 resultAddr, u32 timeoutPtr) { u32 error = __KernelValidateSendMsgPipe(uid, sendBufAddr, sendSize, waitMode, resultAddr); if (error != 0) { return hleLogError(Log::sceKernel, error); @@ -811,13 +808,15 @@ int sceKernelSendMsgPipe(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitMode if (!m) { return hleLogError(Log::sceKernel, error, "bad msgpipe id"); } + if (timeoutPtr && !Memory::IsValid4AlignedAddress(timeoutPtr)) { + return hleLogError(Log::sceKernel, SCE_KERNEL_ERROR_ILLEGAL_ADDR, "bad timeout address"); + } int result = __KernelSendMsgPipe(m, sendBufAddr, sendSize, waitMode, resultAddr, timeoutPtr, false, false); return hleLogDebug(Log::sceKernel, result); } -int sceKernelSendMsgPipeCB(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitMode, u32 resultAddr, u32 timeoutPtr) -{ +int sceKernelSendMsgPipeCB(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitMode, u32 resultAddr, u32 timeoutPtr) { u32 error = __KernelValidateSendMsgPipe(uid, sendBufAddr, sendSize, waitMode, resultAddr); if (error != 0) { return hleLogError(Log::sceKernel, error); @@ -826,6 +825,9 @@ int sceKernelSendMsgPipeCB(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitMo if (!m) { return hleLogError(Log::sceKernel, error, "bad msgpipe id"); } + if (timeoutPtr && !Memory::IsValid4AlignedAddress(timeoutPtr)) { + return hleLogError(Log::sceKernel, SCE_KERNEL_ERROR_ILLEGAL_ADDR, "bad timeout address"); + } // TODO: Verify callback behavior. hleCheckCurrentCallbacks(); @@ -833,8 +835,7 @@ int sceKernelSendMsgPipeCB(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitMo return hleLogDebug(Log::sceKernel, result); } -int sceKernelTrySendMsgPipe(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitMode, u32 resultAddr) -{ +int sceKernelTrySendMsgPipe(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitMode, u32 resultAddr) { u32 error = __KernelValidateSendMsgPipe(uid, sendBufAddr, sendSize, waitMode, resultAddr, true); if (error != 0) { return hleLogError(Log::sceKernel, error); @@ -848,7 +849,7 @@ int sceKernelTrySendMsgPipe(SceUID uid, u32 sendBufAddr, u32 sendSize, u32 waitM return hleLogDebug(Log::sceKernel, result); } -static int __KernelValidateReceiveMsgPipe(SceUID uid, u32 receiveBufAddr, u32 receiveSize, int waitMode, u32 resultAddr, bool tryMode = false) +static int __KernelValidateReceiveMsgPipe(SceUID uid, u32 receiveBufAddr, u32 receiveSize, int waitMode, bool tryMode = false) { if (receiveSize & 0x80000000) { @@ -907,7 +908,7 @@ static int __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSiz int sceKernelReceiveMsgPipe(SceUID uid, u32 receiveBufAddr, u32 receiveSize, u32 waitMode, u32 resultAddr, u32 timeoutPtr) { - u32 error = __KernelValidateReceiveMsgPipe(uid, receiveBufAddr, receiveSize, waitMode, resultAddr); + u32 error = __KernelValidateReceiveMsgPipe(uid, receiveBufAddr, receiveSize, waitMode); if (error != 0) { return hleLogError(Log::sceKernel, error); } @@ -922,7 +923,7 @@ int sceKernelReceiveMsgPipe(SceUID uid, u32 receiveBufAddr, u32 receiveSize, u32 int sceKernelReceiveMsgPipeCB(SceUID uid, u32 receiveBufAddr, u32 receiveSize, u32 waitMode, u32 resultAddr, u32 timeoutPtr) { - u32 error = __KernelValidateReceiveMsgPipe(uid, receiveBufAddr, receiveSize, waitMode, resultAddr); + u32 error = __KernelValidateReceiveMsgPipe(uid, receiveBufAddr, receiveSize, waitMode); if (error != 0) { return hleLogError(Log::sceKernel, error); } @@ -939,7 +940,7 @@ int sceKernelReceiveMsgPipeCB(SceUID uid, u32 receiveBufAddr, u32 receiveSize, u int sceKernelTryReceiveMsgPipe(SceUID uid, u32 receiveBufAddr, u32 receiveSize, u32 waitMode, u32 resultAddr) { - u32 error = __KernelValidateReceiveMsgPipe(uid, receiveBufAddr, receiveSize, waitMode, resultAddr, true); + u32 error = __KernelValidateReceiveMsgPipe(uid, receiveBufAddr, receiveSize, waitMode, true); if (error != 0) { return hleLogError(Log::sceKernel, error); } @@ -966,10 +967,10 @@ int sceKernelCancelMsgPipe(SceUID uid, u32 numSendThreadsAddr, u32 numReceiveThr if (!m->sendWaitingThreads.empty() || !m->receiveWaitingThreads.empty()) hleEatCycles(4000); - if (Memory::IsValidAddress(numSendThreadsAddr)) - Memory::Write_U32((u32) m->sendWaitingThreads.size(), numSendThreadsAddr); - if (Memory::IsValidAddress(numReceiveThreadsAddr)) - Memory::Write_U32((u32) m->receiveWaitingThreads.size(), numReceiveThreadsAddr); + if (Memory::IsValid4AlignedAddress(numSendThreadsAddr)) + Memory::WriteUnchecked_U32((u32) m->sendWaitingThreads.size(), numSendThreadsAddr); + if (Memory::IsValid4AlignedAddress(numReceiveThreadsAddr)) + Memory::WriteUnchecked_U32((u32) m->receiveWaitingThreads.size(), numReceiveThreadsAddr); for (size_t i = 0; i < m->sendWaitingThreads.size(); i++) m->sendWaitingThreads[i].Cancel(uid, SCE_KERNEL_ERROR_WAIT_CANCEL); diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index 2b71e4dced..47fc250360 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -224,10 +224,11 @@ int sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u32 } // Many games pass garbage into optionPtr, it doesn't have any options. + // TODO: Presumably that means that this function simply doesn't have an option parameter? if (optionPtr != 0) { if (!Memory::IsValidRange(optionPtr, 4)) return hleLogWarning(Log::sceKernel, id, "invalid options parameter"); - else if (Memory::Read_U32(optionPtr) > 4) + else if (Memory::ReadUnchecked_U32(optionPtr) > 4) return hleLogDebug(Log::sceKernel, id, "invalid options parameter size"); } return hleLogDebug(Log::sceKernel, id); @@ -328,11 +329,12 @@ void __KernelSemaTimeout(u64 userdata, int cycleslate) { } } +// Assumes timeoutPtr is zero or valid. static void __KernelSetSemaTimeout(PSPSemaphore *s, u32 timeoutPtr) { if (timeoutPtr == 0 || semaWaitTimer == -1) return; - int micro = (int) Memory::Read_U32(timeoutPtr); + int micro = (int) Memory::ReadUnchecked_U32(timeoutPtr); // This happens to be how the hardware seems to time things. if (micro <= 3) @@ -344,6 +346,7 @@ static void __KernelSetSemaTimeout(PSPSemaphore *s, u32 timeoutPtr) { CoreTiming::ScheduleEvent(usToCycles(micro), semaWaitTimer, __KernelGetCurThread()); } +// Assumes timeoutPtr is zero or valid. static int __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, bool processCallbacks) { hleEatCycles(900); @@ -378,6 +381,10 @@ static int __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, bool pro } int sceKernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr) { + if (timeoutPtr && !Memory::IsValid4AlignedAddress(timeoutPtr)) { + return hleLogError(Log::sceKernel, SCE_KERNEL_ERROR_BAD_ARGUMENT, "invalid timeout pointer"); // untested + } + int result = __KernelWaitSema(id, wantedCount, timeoutPtr, false); if (id == 0 && result == SCE_KERNEL_ERROR_UNKNOWN_SEMID) { @@ -389,6 +396,10 @@ int sceKernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr) { } int sceKernelWaitSemaCB(SceUID id, int wantedCount, u32 timeoutPtr) { + if (timeoutPtr && !Memory::IsValid4AlignedAddress(timeoutPtr)) { + return hleLogError(Log::sceKernel, SCE_KERNEL_ERROR_BAD_ARGUMENT, "invalid timeout pointer"); // untested + } + int result = __KernelWaitSema(id, wantedCount, timeoutPtr, true); if (id == 0 && result == SCE_KERNEL_ERROR_UNKNOWN_SEMID) { diff --git a/Core/HLE/sceKernelVTimer.cpp b/Core/HLE/sceKernelVTimer.cpp index 3937add6d3..7544876ab9 100644 --- a/Core/HLE/sceKernelVTimer.cpp +++ b/Core/HLE/sceKernelVTimer.cpp @@ -228,8 +228,8 @@ u32 sceKernelCreateVTimer(const char *name, u32 optParamAddr) { strncpy(vtimer->nvt.name, name, KERNELOBJECT_MAX_NAME_LENGTH); vtimer->nvt.name[KERNELOBJECT_MAX_NAME_LENGTH] = '\0'; - if (optParamAddr != 0) { - u32 size = Memory::Read_U32(optParamAddr); + if (optParamAddr != 0 && Memory::IsValid4AlignedAddress(optParamAddr)) { + u32 size = Memory::ReadUnchecked_U32(optParamAddr); if (size > 4) WARN_LOG_REPORT_ONCE(vtimeropt, Log::sceKernel, "sceKernelCreateVTimer(%s) unsupported options parameter, size = %d", name, size); } @@ -470,9 +470,9 @@ u32 sceKernelReferVTimerStatus(SceUID uid, u32 statusAddr) { return hleLogError(Log::sceKernel, error, "bad timer ID"); } - if (Memory::IsValidAddress(statusAddr)) { + if (Memory::IsValid4AlignedAddress(statusAddr)) { NativeVTimer status = vt->nvt; - u32 size = Memory::Read_U32(statusAddr); + u32 size = Memory::ReadUnchecked_U32(statusAddr); status.current = __getVTimerCurrentTime(vt); Memory::Memcpy(statusAddr, &status, std::min(size, (u32)sizeof(status)), "VTimerStatus"); } diff --git a/Core/HLE/sceMp3.cpp b/Core/HLE/sceMp3.cpp index 87e470c296..e23d987b0b 100644 --- a/Core/HLE/sceMp3.cpp +++ b/Core/HLE/sceMp3.cpp @@ -412,7 +412,7 @@ static int FindMp3Header(AuCtx *ctx, int &header, int end) { for (int offset = 0; offset < end; ++offset) { // If we hit valid sync bits, then we've found a header. if (ptr[offset] == 0xFF && (ptr[offset + 1] & 0xC0) == 0xC0) { - header = bswap32(Memory::Read_U32(addr + offset)); + header = bswap32(Memory::ReadUnchecked_U32(addr + offset)); return offset; } } diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index ee45c7b375..2cb4264d06 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -3200,9 +3200,13 @@ int sceNetAdhocctlScan() { int sceNetAdhocctlGetScanInfo(u32 sizeAddr, u32 bufAddr) { s32_le *buflen = NULL; - if (Memory::IsValidAddress(sizeAddr)) buflen = (s32_le *)Memory::GetPointer(sizeAddr); + if (Memory::IsValidAddress(sizeAddr)) { + buflen = (s32_le *)Memory::GetPointer(sizeAddr); + } SceNetAdhocctlScanInfoEmu *buf = NULL; - if (Memory::IsValidAddress(bufAddr)) buf = (SceNetAdhocctlScanInfoEmu *)Memory::GetPointer(bufAddr); + if (Memory::IsValidAddress(bufAddr)) { + buf = (SceNetAdhocctlScanInfoEmu *)Memory::GetPointer(bufAddr); + } INFO_LOG(Log::sceNet, "sceNetAdhocctlGetScanInfo([%08x]=%i, %08x) at %08x", sizeAddr, Memory::Read_U32(sizeAddr), bufAddr, currentMIPS->pc); if (!g_Config.bEnableWlan) { diff --git a/Core/HLE/sceNetInet.cpp b/Core/HLE/sceNetInet.cpp index 83683c7c94..86c2035460 100644 --- a/Core/HLE/sceNetInet.cpp +++ b/Core/HLE/sceNetInet.cpp @@ -485,7 +485,7 @@ static int sceNetInetSetsockopt(int socket, int level, int optname, u32 optvalPt return hleLogError(Log::sceNet, ERROR_INET_EBADF, "Bad socket #%d", socket); } - u32 optval = optvalPtr ? Memory::Read_U32(optvalPtr) : 0; + const u32 optval = Memory::IsValid4AlignedAddress(optvalPtr) ? Memory::ReadUnchecked_U32(optvalPtr) : 0; INFO_LOG(Log::sceNet, "sceNetInetSetsockopt(%i, %i, %i, %08x, %i) at %08x: Level = %s, OptName = %s, OptValue = %d", socket, level, optname, optvalPtr, optlen, currentMIPS->pc, inetSockoptLevel2str(level).c_str(), inetSockoptName2str(optname, level).c_str(), optval); diff --git a/Core/HLE/sceNp.cpp b/Core/HLE/sceNp.cpp index c66a9f1799..2db1d98efc 100644 --- a/Core/HLE/sceNp.cpp +++ b/Core/HLE/sceNp.cpp @@ -28,10 +28,10 @@ #include "Core/CoreTiming.h" #include "Core/Config.h" #include "Core/HLE/HLE.h" +#include "Core/HLE/HLEUtil.h" #include "Core/HLE/FunctionWrappers.h" #include "Core/HLE/sceNp.h" - bool npAuthInited = false; int npSigninState = NP_SIGNIN_STATUS_NONE; SceNpAuthMemoryStat npAuthMemStat = {}; @@ -354,14 +354,12 @@ param seems to be a struct where offset: +20: 32-bit a pointer to a random data (4 to 8-bytes data max? both 2x 32-bit seems to be a valid pointer). optional handler args? return value >= 0 and <0 seems to be stored at a different location by the game (valid result vs error code?) */ -int sceNpAuthCreateStartRequest(u32 paramAddr) -{ - if (!Memory::IsValidAddress(paramAddr)) - return hleLogError(Log::sceNet, SCE_NP_AUTH_ERROR_INVALID_ARGUMENT, "invalid arg"); - +int sceNpAuthCreateStartRequest(u32 paramAddr) { SceNpAuthRequestParameter params = {}; - int size = Memory::Read_U32(paramAddr); - Memory::Memcpy(¶ms, paramAddr, size); + if (!ReadVariableSizedStruct(paramAddr, ¶ms)) { + return hleLogError(Log::sceNet, SCE_NP_AUTH_ERROR_INVALID_ARGUMENT, "invalid arg"); + } + npServiceId = Memory::GetCharPointer(params.serviceIdAddr); INFO_LOG(Log::sceNet, "%s - Max Version: %u.%u", __FUNCTION__, params.version.major, params.version.minor); diff --git a/Core/HLE/sceP3da.cpp b/Core/HLE/sceP3da.cpp index 0527d0c0dc..f225bfaee0 100644 --- a/Core/HLE/sceP3da.cpp +++ b/Core/HLE/sceP3da.cpp @@ -21,18 +21,17 @@ #include "Core/MemMap.h" #include "Core/Reporting.h" -static u32 sceP3daBridgeInit(u32 channelsNum, u32 samplesNum) -{ - ERROR_LOG_REPORT(Log::sceAudio, "UNIMPL sceP3daBridgeInit(%08x, %08x)", channelsNum, samplesNum); +static u32 sceP3daBridgeInit(u32 channelsNum, u32 samplesNum) { + WARN_LOG(Log::sceAudio, "UNIMPL sceP3daBridgeInit(%08x, %08x)", channelsNum, samplesNum); return hleNoLog(0); } -static u32 sceP3daBridgeExit() -{ - ERROR_LOG_REPORT(Log::sceAudio, "UNIMPL sceP3daBridgeExit()"); +static u32 sceP3daBridgeExit() { + WARN_LOG(Log::sceAudio, "UNIMPL sceP3daBridgeExit()"); return hleNoLog(0); } +// Isn't this just a log2? static inline int getScaleValue(u32 channelsNum) { int val = 0; while (channelsNum > 1) { @@ -42,14 +41,14 @@ static inline int getScaleValue(u32 channelsNum) { return val; } -static u32 sceP3daBridgeCore(u32 p3daCoreAddr, u32 channelsNum, u32 samplesNum, u32 inputAddr, u32 outputAddr) -{ - if (Memory::IsValidAddress(inputAddr) && Memory::IsValidAddress(outputAddr)) { +// What is this?? +static u32 sceP3daBridgeCore(u32 p3daCoreAddr, u32 channelsNum, u32 samplesNum, u32 inputAddr, u32 outputAddr) { + if (Memory::IsValidRange(inputAddr, channelsNum * 4) && Memory::IsValidRange(outputAddr, samplesNum * sizeof(s16) * 2)) { int scaleval = getScaleValue(channelsNum); s16_le *outbuf = (s16_le *)Memory::GetPointerWriteUnchecked(outputAddr); memset(outbuf, 0, samplesNum * sizeof(s16) * 2); for (u32 k = 0; k < channelsNum; k++) { - u32 inaddr = Memory::Read_U32(inputAddr + k * 4); + u32 inaddr = Memory::ReadUnchecked_U32(inputAddr + k * 4); const s16 *inbuf = (const s16 *)Memory::GetPointerUnchecked(inaddr); if (!inbuf) continue; @@ -64,14 +63,12 @@ static u32 sceP3daBridgeCore(u32 p3daCoreAddr, u32 channelsNum, u32 samplesNum, return hleDelayResult(hleLogDebug(Log::sceAudio, 0), "p3da core", 240); } -const HLEFunction sceP3da[] = -{ +const HLEFunction sceP3da[] = { {0X374500A5, &WrapU_UU, "sceP3daBridgeInit", 'x', "xx" }, {0X43F756A2, &WrapU_V, "sceP3daBridgeExit", 'x', "" }, {0X013016F3, &WrapU_UUUUU, "sceP3daBridgeCore", 'x', "xxxxx"}, }; -void Register_sceP3da() -{ +void Register_sceP3da() { RegisterHLEModule("sceP3da", ARRAY_SIZE(sceP3da), sceP3da); } diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index e03da34cda..95515570e0 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -686,6 +686,12 @@ static u32 __sceSasSetVoiceATRAC3(u32 core, int voiceNum, u32 atrac3Context) { return hleLogWarning(Log::sceSas, SCE_SAS_ERROR_INVALID_VOICE, "invalid voicenum"); } + // Not sure what an appropriate range length check is. It's at least 256 though. + if (!Memory::IsValid4AlignedRange(atrac3Context, 256)) { + // Untested + return hleLogError(Log::sceSas, SCE_SAS_ERROR_INVALID_PARAMETER, "invalid ATRAC3 context address"); + } + __SasDrain(); SasVoice &v = sas->voices[voiceNum]; if (v.type == VOICETYPE_ATRAC3) { @@ -695,7 +701,7 @@ static u32 __sceSasSetVoiceATRAC3(u32 core, int voiceNum, u32 atrac3Context) { v.loop = false; v.playing = true; v.atrac3.SetContext(atrac3Context); - Memory::Write_U32(atrac3Context, core + 56 * voiceNum + 20); + Memory::WriteUnchecked_U32(atrac3Context, core + 56 * voiceNum + 20); return hleLogDebug(Log::sceSas, 0); } diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index bd63042446..461f1ae0f0 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -188,6 +188,7 @@ void VagDecoder::DoState(PointerWrap &p) { Do(p, end_); } +// The context pointer is assumed to be valid. int SasAtrac3::SetContext(u32 contextAddr) { contextAddr_ = contextAddr; // Note: On hardware, atracID_ is also stored in the loopNum member of the context.