aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-30 11:40:49 -0400
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-30 11:40:58 -0400
commit37893c68314360071261305a2f8527d8efde8fde (patch)
tree3e595ba7a6b3dc132176f4f0a4c9a47657f01fb9 /src
parentf362528c0447c491bfe00c0bdd5d8c245396a24c (diff)
ro: read Switch 2 NRR hash lists where they are
Switch 2 NRRs carry 3072-bit keys and signatures, so the fields after them (program id, size, kind, hash list offset and count) sit 0x180 bytes later than in a Switch 1 NRR: hash list offset and count at 0x4c0, hashes from 0x4d0 (Kirby Air Riders, Minecraft, Mario Tennis Fever). RegisterModuleInfo read signature bytes as the hash count: Kirby Air Riders read 51 GB of "hashes" (host memory ran out), Minecraft threw bad_alloc and the process ended. Read the fields at the Switch 2 offsets for Switch 2 processes, and reject an NRR whose hash list does not fit inside it.
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/ro/ro.cpp23
1 files changed, 19 insertions, 4 deletions
diff --git a/src/core/hle/service/ro/ro.cpp b/src/core/hle/service/ro/ro.cpp
index 335efa3ad3..2af4f1cf58 100644
--- a/src/core/hle/service/ro/ro.cpp
+++ b/src/core/hle/service/ro/ro.cpp
@@ -356,6 +356,22 @@ public:
// Read NRR.
NrrHeader header{};
process->GetMemory().ReadBlock(nrr_address, std::addressof(header), sizeof(header));
+ size_t hashes_offset = header.GetHashesOffset();
+ u32 num_hashes = header.GetNumHashes();
+ if (process->IsSwitch2()) {
+ // Switch 2 NRRs carry 3072-bit keys and signatures: the fields after them (program
+ // id, size, kind, hash list offset and count) sit 0x180 bytes later, the hash list
+ // offset and count at 0x4c0.
+ std::array<u32, 2> fields{};
+ process->GetMemory().ReadBlock(nrr_address + 0x4c0, fields.data(), sizeof(fields));
+ hashes_offset = fields[0];
+ num_hashes = fields[1];
+ }
+ // The hash list lies inside the NRR (read as a Switch 1 header, a Switch 2 one asked for
+ // 51 GB of hashes).
+ R_UNLESS(hashes_offset <= nrr_size &&
+ num_hashes <= (nrr_size - hashes_offset) / sizeof(Sha256Hash),
+ RO::ResultInvalidNrr);
// Set NRR info.
context->SetNrrInfoInUse(nrr_info, true);
@@ -363,10 +379,9 @@ public:
nrr_info->nrr_heap_size = nrr_size;
// Read NRR hash list.
- nrr_info->hashes.resize(header.GetNumHashes());
- process->GetMemory().ReadBlock(nrr_address + header.GetHashesOffset(),
- nrr_info->hashes.data(),
- sizeof(Sha256Hash) * header.GetNumHashes());
+ nrr_info->hashes.resize(num_hashes);
+ process->GetMemory().ReadBlock(nrr_address + hashes_offset, nrr_info->hashes.data(),
+ sizeof(Sha256Hash) * num_hashes);
R_SUCCEED();
}