diff --git a/sysmodules/rosalina/include/gdb/net.h b/sysmodules/rosalina/include/gdb/net.h index 10a950b..199bf65 100644 --- a/sysmodules/rosalina/include/gdb/net.h +++ b/sysmodules/rosalina/include/gdb/net.h @@ -33,7 +33,7 @@ u8 GDB_ComputeChecksum(const char *packetData, u32 len); void GDB_EncodeHex(char *dst, const void *src, u32 len); u32 GDB_DecodeHex(void *dst, const char *src, u32 len); -u32 GDB_EscapeBinaryData(void *dst, const void *src, u32 len, u32 maxLen); +u32 GDB_EscapeBinaryData(u32 *encodedCount, void *dst, const void *src, u32 len, u32 maxLen); u32 GDB_UnescapeBinaryData(void *dst, const void *src, u32 len); const char *GDB_ParseIntegerList(u32 *dst, const char *src, u32 nb, char sep, char lastSep, u32 base, bool allowPrefix); const char *GDB_ParseHexIntegerList(u32 *dst, const char *src, u32 nb, char lastSep); diff --git a/sysmodules/rosalina/source/gdb/net.c b/sysmodules/rosalina/source/gdb/net.c index 0fe93c7..9602c2b 100644 --- a/sysmodules/rosalina/source/gdb/net.c +++ b/sysmodules/rosalina/source/gdb/net.c @@ -75,15 +75,19 @@ u32 GDB_DecodeHex(void *dst, const char *src, u32 len) return (!ok) ? i - 1 : i; } -u32 GDB_EscapeBinaryData(void *dst, const void *src, u32 len, u32 maxLen) +u32 GDB_EscapeBinaryData(u32 *encodedCount, void *dst, const void *src, u32 len, u32 maxLen) { u8 *dst8 = (u8 *)dst; const u8 *src8 = (const u8 *)src; - for(u32 i = 0; i < len && (u32)dst8 - (u32)dst < maxLen; i++) + maxLen = maxLen >= len ? len : maxLen; + + while((uintptr_t)dst8 < (uintptr_t)dst + maxLen) { if(*src8 == '$' || *src8 == '#' || *src8 == '}' || *src8 == '*') { + if ((uintptr_t)dst8 + 1 >= (uintptr_t)dst + maxLen) + break; *dst8++ = '}'; *dst8++ = *src8++ ^ 0x20; } @@ -91,7 +95,8 @@ u32 GDB_EscapeBinaryData(void *dst, const void *src, u32 len, u32 maxLen) *dst8++ = *src8++; } - return dst8 - (u8 *)dst; + *encodedCount = dst8 - (u8 *)dst; + return src8 - (u8 *)src; } u32 GDB_UnescapeBinaryData(void *dst, const void *src, u32 len) @@ -99,7 +104,7 @@ u32 GDB_UnescapeBinaryData(void *dst, const void *src, u32 len) u8 *dst8 = (u8 *)dst; const u8 *src8 = (const u8 *)src; - for(u32 i = 0; i < len; i++) + while((uintptr_t)src8 < (uintptr_t)src + len) { if(*src8 == '}') { diff --git a/sysmodules/rosalina/source/gdb/tio.c b/sysmodules/rosalina/source/gdb/tio.c index 09a22e1..9da3428 100644 --- a/sysmodules/rosalina/source/gdb/tio.c +++ b/sysmodules/rosalina/source/gdb/tio.c @@ -332,6 +332,7 @@ GDB_DECLARE_TIO_HANDLER(Close) GDB_DECLARE_TIO_HANDLER(Read) { + // GDB, with it code quality we're all aware of, always ask to read GDB_BUF_LEN, even if the packet can't fit... // "$F;#XX" char buf2[GDB_BUF_LEN - 4]; u8 buf[sizeof(buf2) - 2 - 8]; @@ -355,10 +356,13 @@ GDB_DECLARE_TIO_HANDLER(Read) if (err != 0) return GDB_TioReplyErrno(ctx, err); - int pos = sprintf(buf2, "F%lx;", (u32)numRead); - u32 actualCount = GDB_EscapeBinaryData(buf2 + pos, buf, (u32)numRead, sizeof(buf)); + char hdr[16]; + u32 encodedCount; + u32 actualCount = GDB_EscapeBinaryData(&encodedCount, buf2 + 10, buf, (u32)numRead, sizeof(buf)); + sprintf(hdr, "F%08lx;", (u32)actualCount); // buffer might not fit the entire read data + memcpy(buf2, hdr, 10); - return GDB_SendPacket(ctx, buf2, pos + actualCount); + return GDB_SendPacket(ctx, buf2, 10 + encodedCount); } GDB_DECLARE_TIO_HANDLER(Write) @@ -448,9 +452,10 @@ GDB_DECLARE_TIO_HANDLER(Stat) GDB_TioMakeStructStat(&gdbStFinal, &gdbSt); char buf[3 + 2 * sizeof(struct gdbhio_stat)] = "F0;"; - u32 actualCount = GDB_EscapeBinaryData(buf + 3, buf, sizeof(struct gdbhio_stat), 2 * sizeof(struct gdbhio_stat)); + u32 encodedCount; + GDB_EscapeBinaryData(&encodedCount, buf + 3, buf, sizeof(struct gdbhio_stat), 2 * sizeof(struct gdbhio_stat)); - return GDB_SendPacket(ctx, buf, 3 + actualCount); + return GDB_SendPacket(ctx, buf, 3 + encodedCount); } GDB_DECLARE_TIO_HANDLER(Unlink)