From 5a7eecc3adfb179335d921725a3b60c622e92836 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 22 Jan 2020 20:14:06 -0800 Subject: [PATCH] loader: provide default arguments (zero byte) to NSOs Certain newer unity games (Terraria, Pokemon Mystery Dungeon) require that the argument region be populated. Failure to do so results in an integer underflow in argument count, and eventually an unmapped read at 0x800000000. Providing this default fixes this. Note that the behavior of official software is as yet unverified, arguments-wise. --- src/core/loader/nso.cpp | 11 ++++++++--- src/core/loader/nso.h | 2 ++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index 515c5accbd..044067a5bd 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp @@ -97,7 +97,8 @@ std::optional AppLoader_NSO::LoadModule(Kernel::Process& process, if (nso_header.IsSegmentCompressed(i)) { data = DecompressSegment(data, nso_header.segments[i]); } - program_image.resize(nso_header.segments[i].location + data.size()); + program_image.resize(nso_header.segments[i].location + + PageAlignSize(static_cast(data.size()))); std::memcpy(program_image.data() + nso_header.segments[i].location, data.data(), data.size()); codeset.segments[i].addr = nso_header.segments[i].location; @@ -105,8 +106,12 @@ std::optional AppLoader_NSO::LoadModule(Kernel::Process& process, codeset.segments[i].size = PageAlignSize(static_cast(data.size())); } - if (should_pass_arguments && !Settings::values.program_args.empty()) { - const auto arg_data = Settings::values.program_args; + if (should_pass_arguments) { + std::vector arg_data{Settings::values.program_args.begin(), + Settings::values.program_args.end()}; + if (arg_data.empty()) { + arg_data.resize(NSO_ARGUMENT_DEFAULT_SIZE); + } codeset.DataSegment().size += NSO_ARGUMENT_DATA_ALLOCATION_SIZE; NSOArgumentHeader args_header{ NSO_ARGUMENT_DATA_ALLOCATION_SIZE, static_cast(arg_data.size()), {}}; diff --git a/src/core/loader/nso.h b/src/core/loader/nso.h index 58cbe162db..d2d600cd9a 100644 --- a/src/core/loader/nso.h +++ b/src/core/loader/nso.h @@ -56,6 +56,8 @@ static_assert(sizeof(NSOHeader) == 0x100, "NSOHeader has incorrect size."); static_assert(std::is_trivially_copyable_v, "NSOHeader must be trivially copyable."); constexpr u64 NSO_ARGUMENT_DATA_ALLOCATION_SIZE = 0x9000; +// NOTE: Official software default argument state is unverified. +constexpr u64 NSO_ARGUMENT_DEFAULT_SIZE = 1; struct NSOArgumentHeader { u32_le allocated_size;