Merge pull request #22080 from hrydgard/fix-debugger-websocket-review

Core/Debugger/Websocket review and fixes by Claude
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2026-08-11 18:13:29 +02:00
commit 3806d00e58
3 files changed
+18 -3

No files matched your search

@@ -446,6 +446,10 @@ void WebSocketMemoryBreakpointRemove(DebuggerRequest &req) {
uint32_t size;
if (!req.ParamU32("size", &size))
return;
// Matches the check in WebSocketMemoryBreakpointParams::Parse() (used by add/update) -
// without it, a crafted size could wrap address + size below address.
if (address + size < address)
return req.Fail("Size is too large");
// Route the actual breakpoint manipulation to the CPU thread instead of poking at it directly
// from this WebSocket handler thread - see Core_RunOnCPUThread() in Core.h.
@@ -51,8 +51,12 @@ static bool StreamBufferToDataURI(DebuggerRequest &req, const GPUDebugBuffer &bu
if (stackWidth > 0) {
u32 totalPixels = w * h;
w = stackWidth;
while ((totalPixels % w) != 0)
// stackWidth is client-supplied and otherwise unbounded; since totalPixels
// is the real (small) buffer size, clamping to it bounds this loop to at
// most totalPixels iterations instead of up to ~2 billion for a huge value.
// Keep it at least 1 to avoid a divide by zero below.
w = std::max<u32>(1, std::min((u32)stackWidth, totalPixels));
while (w > 1 && (totalPixels % w) != 0)
--w;
h = totalPixels / w;
}
@@ -384,6 +388,11 @@ void WebSocketGPUBufferTexture(DebuggerRequest &req) {
u32 level = 0;
if (!req.ParamU32("level", &level, false, DebuggerParamType::OPTIONAL))
return;
// Sanity check the level, to avoid overflow hacks. Also it just can't be very high,
// we currently support 12 levels for replacement (the PSP only supports 8).
if (level > 12) {
return req.Fail("Invalid level");
}
GenericStreamBuffer(req, [level](const GPUDebugBuffer *&buf, bool *isFramebuffer) {
return GPUStepping::GPU_GetCurrentTexture(buf, level, isFramebuffer);
+3 -1
View File
@@ -153,7 +153,9 @@ bool ReplayExecuteBlob(int version, const std::vector<uint8_t> &data) {
i += sizeof(ReplayItemHeader);
if ((int)item.info.action & (int)ReplayAction::MASK_SIDEDATA) {
if (i + item.info.size > sz) {
// Subtraction-based check (rather than i + item.info.size > sz) avoids
// wraparound on platforms where size_t is 32-bit. Bound checking because memcpy.
if (item.info.size > sz - i) {
ERROR_LOG(Log::System, "Truncated replay data at %lld during side data", (long long)i);
break;
}