Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DiscIO/VolumeVerifier: Avoid out-of-bounds reads on trimmed Wii ISOs. #10838

Conversation

AdmiralCurtiss
Copy link
Contributor

@JosJuice Please check if this makes sense or can be implemented better/differently.

Copy link
Member

@JosJuice JosJuice left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an alternative solution that would cause the "This disc image is too small and lacks some data" message to trigger instead of the "Integrity check failed for block" message. (In practice the former message will be triggered anyway due to missing data beyond the 4 GiB mark, so for practical purposes the only difference is whether the latter message will be shown.) It is as follows: When if (m_progress + bytes_to_read > m_max_progress) is taken, set group_read to false. (Probably also content_read for consistency, though as far as I know there's no crash associated with that one.)

I think not getting the "Integrity check failed for block" message is cleaner in that the information given to the user is more specific about the problem, but if you do want to go with the approach you currently have, here are my comments on it:

@@ -1215,8 +1215,10 @@ void VolumeVerifier::Process()
{
const u64 block_offset = group.offset + offset_in_group;

if (read_succeeded && m_volume.CheckBlockIntegrity(
block_index, m_data.data() + offset_in_group, group.partition))
if (read_succeeded && offset_in_group < byte_increment &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should use bytes_to_read or m_data.size() (the two of them have the same value at this point in the code) instead of byte_increment.

The difference is that if the end of a group overlaps with the start of another group (which should never happen in practice, but support for it is implemented just in case), byte_increment doesn't include the overlapping part.

if (read_succeeded && m_volume.CheckBlockIntegrity(
block_index, m_data.data() + offset_in_group, group.partition))
if (read_succeeded && offset_in_group < byte_increment &&
(byte_increment - offset_in_group) >= VolumeWii::BLOCK_TOTAL_SIZE &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of having two different statements that check byte_increment, can't you have just one statement? offset_in_group + VolumeWii::BLOCK_TOTAL_SIZE <= byte_increment

@AdmiralCurtiss AdmiralCurtiss force-pushed the volume-verifier-out-of-bounds-read branch from fdac762 to 10407cc Compare July 13, 2022 11:44
@AdmiralCurtiss
Copy link
Contributor Author

Like this? Seems to fix the crash, yes.

@AdmiralCurtiss AdmiralCurtiss merged commit bae715f into dolphin-emu:master Jul 13, 2022
@AdmiralCurtiss AdmiralCurtiss deleted the volume-verifier-out-of-bounds-read branch July 13, 2022 16:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
2 participants