DolReader: Fix integer wraparound
A malicious dol could theoretically use integer wraparound to bypass bounds checking and cause DolReader to read past the end of m_bytes. Could result in crashes, wasting large amounts of memory, or even the disclosure of heap memory contents.
This commit is contained in:
@@ -55,17 +55,20 @@ bool DolReader::Initialize(std::span<const u8> buffer)
|
|||||||
{
|
{
|
||||||
if ((m_dolheader.textAddress[i] & 31) != 0 || (m_dolheader.textSize[i] & 31) != 0)
|
if ((m_dolheader.textAddress[i] & 31) != 0 || (m_dolheader.textSize[i] & 31) != 0)
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(BOOT,
|
ERROR_LOG_FMT(BOOT,
|
||||||
"Text section {} is not 32-byte aligned: address = 0x{:08x}, size = 0x{:x}",
|
"Text section {} is not 32-byte aligned: address = 0x{:08x}, size = 0x{:x}",
|
||||||
i, m_dolheader.textAddress[i], m_dolheader.textSize[i]);
|
i, m_dolheader.textAddress[i], m_dolheader.textSize[i]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer.size() < m_dolheader.textOffset[i] + m_dolheader.textSize[i])
|
const std::size_t section_offset = m_dolheader.textOffset[i];
|
||||||
|
const std::size_t section_size = m_dolheader.textSize[i];
|
||||||
|
|
||||||
|
if (buffer.size() < section_offset || (buffer.size() - section_offset) < section_size)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const u8* text_start = &buffer[m_dolheader.textOffset[i]];
|
const u8* text_start = &buffer[section_offset];
|
||||||
m_text_sections.emplace_back(text_start, &text_start[m_dolheader.textSize[i]]);
|
m_text_sections.emplace_back(text_start, &text_start[section_size]);
|
||||||
|
|
||||||
for (unsigned int j = 0; !m_is_wii && j < (m_dolheader.textSize[i] / sizeof(u32)); ++j)
|
for (unsigned int j = 0; !m_is_wii && j < (m_dolheader.textSize[i] / sizeof(u32)); ++j)
|
||||||
{
|
{
|
||||||
@@ -86,11 +89,11 @@ bool DolReader::Initialize(std::span<const u8> buffer)
|
|||||||
{
|
{
|
||||||
if (m_dolheader.dataSize[i] != 0)
|
if (m_dolheader.dataSize[i] != 0)
|
||||||
{
|
{
|
||||||
u32 section_size = m_dolheader.dataSize[i];
|
const std::size_t section_size = m_dolheader.dataSize[i];
|
||||||
u32 section_offset = m_dolheader.dataOffset[i];
|
const std::size_t section_offset = m_dolheader.dataOffset[i];
|
||||||
if ((m_dolheader.dataAddress[i] & 31) != 0 || (section_size & 31) != 0)
|
if ((m_dolheader.dataAddress[i] & 31) != 0 || (section_size & 31) != 0)
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(BOOT,
|
ERROR_LOG_FMT(BOOT,
|
||||||
"Data section {} is not 32-byte aligned: address = 0x{:08x}, size = 0x{:x}",
|
"Data section {} is not 32-byte aligned: address = 0x{:08x}, size = 0x{:x}",
|
||||||
i, m_dolheader.dataAddress[i], section_size);
|
i, m_dolheader.dataAddress[i], section_size);
|
||||||
return false;
|
return false;
|
||||||
@@ -101,8 +104,7 @@ bool DolReader::Initialize(std::span<const u8> buffer)
|
|||||||
|
|
||||||
std::vector<u8> data(section_size);
|
std::vector<u8> data(section_size);
|
||||||
const u8* data_start = &buffer[section_offset];
|
const u8* data_start = &buffer[section_offset];
|
||||||
std::memcpy(&data[0], data_start,
|
std::memcpy(&data[0], data_start, std::min(section_size, buffer.size() - section_offset));
|
||||||
std::min((size_t)section_size, buffer.size() - section_offset));
|
|
||||||
m_data_sections.emplace_back(data);
|
m_data_sections.emplace_back(data);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
Reference in New Issue
Block a user