CDVD: Fix an out of bounds read exploit in MG SCMD handlers
Some checks are pending
🐧 Linux Builds / AppImage (push) Waiting to run
🐧 Linux Builds / Flatpak (push) Waiting to run
🍎 MacOS Builds / Defaults (push) Waiting to run
🖥️ Windows Builds / Lint VS Project Files (push) Waiting to run
🖥️ Windows Builds / SSE4 (push) Blocked by required conditions
🖥️ Windows Builds / AVX2 (push) Blocked by required conditions
🖥️ Windows Builds / CMake (push) Waiting to run

This commit is contained in:
Ty 2025-12-12 15:46:36 +00:00
parent d0c54de330
commit 8164f2b2db

View File

@ -2942,8 +2942,19 @@ static void cdvdWrite16(u8 rt) // SCOMMAND
bit_ofs = mg_BIToffset(&cdvd.mg_buffer[0]);
memcpy(&cdvd.mg_kbit[0], &cdvd.mg_buffer[bit_ofs - 0x20], 0x10);
memcpy(&cdvd.mg_kcon[0], &cdvd.mg_buffer[bit_ofs - 0x10], 0x10);
const size_t buf_size = sizeof(cdvd.mg_buffer);
if (bit_ofs < 0x20 || (size_t)bit_ofs > buf_size)
{
fail_pol_cal();
break;
}
const size_t kbit_ofs = bit_ofs - 0x20;
const size_t kcon_ofs = bit_ofs - 0x10;
std::memcpy(&cdvd.mg_kbit[0], &cdvd.mg_buffer[kbit_ofs], 0x10);
std::memcpy(&cdvd.mg_kcon[0], &cdvd.mg_buffer[kcon_ofs], 0x10);
if ((cdvd.mg_buffer[bit_ofs + 5] || cdvd.mg_buffer[bit_ofs + 6] || cdvd.mg_buffer[bit_ofs + 7]) ||
(GetBufferU16(&cdvd.mg_buffer[0],bit_ofs + 4) * 16 + bit_ofs + 8 + 16 != GetBufferU16(&cdvd.mg_buffer[0], 0x14)))
@ -2969,7 +2980,31 @@ static void cdvdWrite16(u8 rt) // SCOMMAND
{
SetSCMDResultSize(3); //in:0
const int bit_ofs = mg_BIToffset(&cdvd.mg_buffer[0]);
memcpy(&cdvd.mg_buffer[0], &cdvd.mg_buffer[bit_ofs], static_cast<size_t>(8 + 16 * static_cast<int>(cdvd.mg_buffer[bit_ofs + 4])));
if (bit_ofs < 0)
{
fail_pol_cal();
break;
}
const size_t bufsize = sizeof(cdvd.mg_buffer);
const size_t ofs = static_cast<size_t>(bit_ofs);
if (ofs > bufsize - 5) // Make sure we can read the block count
{
fail_pol_cal();
break;
}
const unsigned int blocks = static_cast<unsigned int>(cdvd.mg_buffer[ofs + 4]);
const size_t copy_len = 8 + 16 * static_cast<size_t>(blocks);
if (copy_len > bufsize - ofs) // Make sure we can read the blocks
{
fail_pol_cal();
break;
}
std::memmove(&cdvd.mg_buffer[0], &cdvd.mg_buffer[ofs], copy_len);
cdvd.mg_maxsize = 0; // don't allow any write
cdvd.mg_size = 8 + 16 * cdvd.mg_buffer[4]; //new offset, i just moved the data