mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-01 20:18:15 +01:00
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>
21 lines
669 B
C++
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;
|
|
}
|