Files
ppsspp/Core/HLE/HLEUtil.h
T
Henrik RydgårdandClaude Opus 5.5 0a778a13ff 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>
2026-10-31 11:26:03 +01:00

21 lines
669 B
C++

#pragma once
#include <cstring>
#include "Core/MemMap.h"
// Used in various places in the PSP OS.
template<typename T> bool ReadVariableSizedStruct(u32 addr, T *out) {
if (!Memory::IsValid4AlignedAddress(addr)) {
return false;
}
int size = Memory::ReadUnchecked_U32(addr);
if (size < 0 || !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::MemcpyUnchecked(out, addr, std::min(size, (int)sizeof(*out)));
return true;
}