HLE: Check more guest buffers by their full length, and an empty insert

Calls that checked one byte of a game's buffer and then wrote or read the
whole thing, or trusted a negative length:
- sceNetEtherNtostr/Strton, the apctl BSS descriptor calls, GetState and
  sceNetGetDropRate.
- sceNpAuthGetTicket wrote its whole ticket whatever the length; it's
  now built locally and written once the buffer is known to hold it.
  sceNpAuthGetTicketParam checked its limits after copying, and walked
  ticket params past the ticket's end.
- sceNp2's communication ID and passphrase, a negative maxServerIds, and
  an unchecked unknown1Ptr.
- sceParseUri's work area and scheme string, sceParseHttp's negative
  header length and value address, and ReadVariableSizedStruct's size.
- sceKernelCreateLwMutex initialized the work area without checking it
  at all, and the other LwMutex calls checked one byte of it.
- sceNetAdhocctlGetScanInfo cleared the length the game gave, of a
  buffer checked by one byte (or any length, negative ones included).

Also: a game mode join inserted at begin() + 1 into a possibly empty
list of players.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-10-31 11:26:03 +01:00
1 parent c0e750726f
commit 0a778a13ff
9 files changed
+127 -67

No files matched your search

+11 -7
View File
@@ -609,6 +609,11 @@ int sceKernelCreateLwMutex(MIPSState *mips, u32 workareaPtr, const char *name, u
return hleLogError(Log::sceKernel, SCE_KERNEL_ERROR_ILLEGAL_COUNT);
}
auto workarea = PSPPointer<NativeLwMutexWorkarea>::Create(workareaPtr);
if (!workarea.IsValid()) {
return hleLogError(Log::sceKernel, SCE_KERNEL_ERROR_ILLEGAL_ADDR, "bad workarea");
}
LwMutex *mutex = new LwMutex();
SceUID id = kernelObjects.Create(mutex);
mutex->nm.size = sizeof(mutex->nm);
@@ -618,7 +623,6 @@ int sceKernelCreateLwMutex(MIPSState *mips, u32 workareaPtr, const char *name, u
mutex->nm.uid = id;
mutex->nm.workarea = workareaPtr;
mutex->nm.initialCount = initialCount;
auto workarea = PSPPointer<NativeLwMutexWorkarea>::Create(workareaPtr);
workarea->init();
workarea->lockLevel = initialCount;
if (initialCount == 0)
@@ -664,7 +668,7 @@ bool __KernelUnlockLwMutexForThread(LwMutex *mutex, T workarea, SceUID threadID,
int sceKernelDeleteLwMutex(u32 workareaPtr) {
DEBUG_LOG(Log::sceKernel, "sceKernelDeleteLwMutex(%08x)", workareaPtr);
if (!workareaPtr || !Memory::IsValidAddress(workareaPtr))
if (!workareaPtr || !Memory::IsValidRange(workareaPtr, sizeof(NativeLwMutexWorkarea)))
return hleLogError(Log::sceKernel, SCE_KERNEL_ERROR_ILLEGAL_ADDR);
auto workarea = PSPPointer<NativeLwMutexWorkarea>::Create(workareaPtr);
@@ -798,7 +802,7 @@ void __KernelLwMutexEndCallback(SceUID threadID, SceUID prevCallbackId)
}
int sceKernelTryLockLwMutex(u32 workareaPtr, int count) {
if (!Memory::IsValidAddress(workareaPtr)) {
if (!Memory::IsValidRange(workareaPtr, sizeof(NativeLwMutexWorkarea))) {
return hleLogError(Log::sceKernel, SCE_KERNEL_ERROR_ACCESS_ERROR, "Bad workarea pointer for LwMutex");
}
@@ -816,7 +820,7 @@ int sceKernelTryLockLwMutex(u32 workareaPtr, int count) {
}
int sceKernelTryLockLwMutex_600(u32 workareaPtr, int count) {
if (!Memory::IsValidAddress(workareaPtr)) {
if (!Memory::IsValidRange(workareaPtr, sizeof(NativeLwMutexWorkarea))) {
return hleLogError(Log::sceKernel, SCE_KERNEL_ERROR_ACCESS_ERROR, "Bad workarea pointer for LwMutex");
}
@@ -833,7 +837,7 @@ int sceKernelTryLockLwMutex_600(u32 workareaPtr, int count) {
}
int sceKernelLockLwMutex(u32 workareaPtr, int count, u32 timeoutPtr) {
if (!Memory::IsValidAddress(workareaPtr)) {
if (!Memory::IsValidRange(workareaPtr, sizeof(NativeLwMutexWorkarea))) {
return hleLogError(Log::sceKernel, SCE_KERNEL_ERROR_ACCESS_ERROR, "Bad workarea pointer for LwMutex");
}
@@ -865,7 +869,7 @@ int sceKernelLockLwMutex(u32 workareaPtr, int count, u32 timeoutPtr) {
}
int sceKernelLockLwMutexCB(u32 workareaPtr, int count, u32 timeoutPtr) {
if (!Memory::IsValidAddress(workareaPtr)) {
if (!Memory::IsValidRange(workareaPtr, sizeof(NativeLwMutexWorkarea))) {
return hleLogError(Log::sceKernel, SCE_KERNEL_ERROR_ACCESS_ERROR, "Bad workarea pointer for LwMutex");
}
@@ -897,7 +901,7 @@ int sceKernelLockLwMutexCB(u32 workareaPtr, int count, u32 timeoutPtr) {
}
int sceKernelUnlockLwMutex(u32 workareaPtr, int count) {
if (!Memory::IsValidAddress(workareaPtr)) {
if (!Memory::IsValidRange(workareaPtr, sizeof(NativeLwMutexWorkarea))) {
return hleLogError(Log::sceKernel, SCE_KERNEL_ERROR_ACCESS_ERROR, "Bad workarea pointer for LwMutex");
}