diff options
| author | 2019-05-09 20:41:33 -0400 | |
|---|---|---|
| committer | 2019-05-09 21:28:36 -0400 | |
| commit | c823cf6594c2ed8f69c84cabb9ed307496a55eff (patch) | |
| tree | 7bd3aac7e6c5cce1a136cc518e1c6c342e70c342 /src | |
| parent | Merge pull request #2437 from lioncash/audctl (diff) | |
| download | yuzu-c823cf6594c2ed8f69c84cabb9ed307496a55eff.tar.gz yuzu-c823cf6594c2ed8f69c84cabb9ed307496a55eff.tar.xz yuzu-c823cf6594c2ed8f69c84cabb9ed307496a55eff.zip | |
service/set: Correct and simplify behavior related to copying language codes
This corrects cases where it was possible to write more entries into the
write buffer than were requested. Now, we check the size of the buffer
before actually writing into them.
We were also returning the wrong value for
GetAvailableLanguageCodeCount2(). This was previously returning 64, but
only 17 should have been returned. 64 entries is the size of the static
array used in MakeLanguageCode() within the service binary itself, but
isn't the actual total number of language codes present.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/set/set.cpp | 56 |
1 files changed, 22 insertions, 34 deletions
diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp index 4ecb6bcef..298d85011 100644 --- a/src/core/hle/service/set/set.cpp +++ b/src/core/hle/service/set/set.cpp | |||
| @@ -2,16 +2,15 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | ||
| 5 | #include <chrono> | 6 | #include <chrono> |
| 6 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 7 | #include "core/hle/ipc_helpers.h" | 8 | #include "core/hle/ipc_helpers.h" |
| 8 | #include "core/hle/kernel/client_port.h" | ||
| 9 | #include "core/hle/kernel/client_session.h" | ||
| 10 | #include "core/hle/service/set/set.h" | 9 | #include "core/hle/service/set/set.h" |
| 11 | #include "core/settings.h" | 10 | #include "core/settings.h" |
| 12 | 11 | ||
| 13 | namespace Service::Set { | 12 | namespace Service::Set { |
| 14 | 13 | namespace { | |
| 15 | constexpr std::array<LanguageCode, 17> available_language_codes = {{ | 14 | constexpr std::array<LanguageCode, 17> available_language_codes = {{ |
| 16 | LanguageCode::JA, | 15 | LanguageCode::JA, |
| 17 | LanguageCode::EN_US, | 16 | LanguageCode::EN_US, |
| @@ -32,41 +31,35 @@ constexpr std::array<LanguageCode, 17> available_language_codes = {{ | |||
| 32 | LanguageCode::ZH_HANT, | 31 | LanguageCode::ZH_HANT, |
| 33 | }}; | 32 | }}; |
| 34 | 33 | ||
| 35 | constexpr std::size_t pre4_0_0_max_entries = 0xF; | 34 | constexpr std::size_t pre4_0_0_max_entries = 15; |
| 36 | constexpr std::size_t post4_0_0_max_entries = 0x40; | 35 | constexpr std::size_t post4_0_0_max_entries = 17; |
| 37 | 36 | ||
| 38 | constexpr ResultCode ERR_INVALID_LANGUAGE{ErrorModule::Settings, 625}; | 37 | constexpr ResultCode ERR_INVALID_LANGUAGE{ErrorModule::Settings, 625}; |
| 39 | 38 | ||
| 40 | LanguageCode GetLanguageCodeFromIndex(std::size_t index) { | 39 | void PushResponseLanguageCode(Kernel::HLERequestContext& ctx, std::size_t num_language_codes) { |
| 41 | return available_language_codes.at(index); | 40 | IPC::ResponseBuilder rb{ctx, 3}; |
| 41 | rb.Push(RESULT_SUCCESS); | ||
| 42 | rb.Push(static_cast<u32>(num_language_codes)); | ||
| 42 | } | 43 | } |
| 43 | 44 | ||
| 44 | template <std::size_t size> | 45 | void GetAvailableLanguageCodesImpl(Kernel::HLERequestContext& ctx, std::size_t max_size) { |
| 45 | static std::array<LanguageCode, size> MakeLanguageCodeSubset() { | 46 | const std::size_t requested_amount = ctx.GetWriteBufferSize() / sizeof(LanguageCode); |
| 46 | std::array<LanguageCode, size> arr; | 47 | const std::size_t copy_amount = std::min(requested_amount, max_size); |
| 47 | std::copy_n(available_language_codes.begin(), size, arr.begin()); | 48 | const std::size_t copy_size = copy_amount * sizeof(LanguageCode); |
| 48 | return arr; | 49 | |
| 50 | ctx.WriteBuffer(available_language_codes.data(), copy_size); | ||
| 51 | PushResponseLanguageCode(ctx, copy_amount); | ||
| 49 | } | 52 | } |
| 53 | } // Anonymous namespace | ||
| 50 | 54 | ||
| 51 | static void PushResponseLanguageCode(Kernel::HLERequestContext& ctx, std::size_t max_size) { | 55 | LanguageCode GetLanguageCodeFromIndex(std::size_t index) { |
| 52 | IPC::ResponseBuilder rb{ctx, 3}; | 56 | return available_language_codes.at(index); |
| 53 | rb.Push(RESULT_SUCCESS); | ||
| 54 | if (available_language_codes.size() > max_size) { | ||
| 55 | rb.Push(static_cast<u32>(max_size)); | ||
| 56 | } else { | ||
| 57 | rb.Push(static_cast<u32>(available_language_codes.size())); | ||
| 58 | } | ||
| 59 | } | 57 | } |
| 60 | 58 | ||
| 61 | void SET::GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx) { | 59 | void SET::GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx) { |
| 62 | LOG_DEBUG(Service_SET, "called"); | 60 | LOG_DEBUG(Service_SET, "called"); |
| 63 | 61 | ||
| 64 | if (available_language_codes.size() > pre4_0_0_max_entries) { | 62 | GetAvailableLanguageCodesImpl(ctx, pre4_0_0_max_entries); |
| 65 | ctx.WriteBuffer(MakeLanguageCodeSubset<pre4_0_0_max_entries>()); | ||
| 66 | } else { | ||
| 67 | ctx.WriteBuffer(available_language_codes); | ||
| 68 | } | ||
| 69 | PushResponseLanguageCode(ctx, pre4_0_0_max_entries); | ||
| 70 | } | 63 | } |
| 71 | 64 | ||
| 72 | void SET::MakeLanguageCode(Kernel::HLERequestContext& ctx) { | 65 | void SET::MakeLanguageCode(Kernel::HLERequestContext& ctx) { |
| @@ -87,12 +80,7 @@ void SET::MakeLanguageCode(Kernel::HLERequestContext& ctx) { | |||
| 87 | void SET::GetAvailableLanguageCodes2(Kernel::HLERequestContext& ctx) { | 80 | void SET::GetAvailableLanguageCodes2(Kernel::HLERequestContext& ctx) { |
| 88 | LOG_DEBUG(Service_SET, "called"); | 81 | LOG_DEBUG(Service_SET, "called"); |
| 89 | 82 | ||
| 90 | if (available_language_codes.size() > post4_0_0_max_entries) { | 83 | GetAvailableLanguageCodesImpl(ctx, post4_0_0_max_entries); |
| 91 | ctx.WriteBuffer(MakeLanguageCodeSubset<post4_0_0_max_entries>()); | ||
| 92 | } else { | ||
| 93 | ctx.WriteBuffer(available_language_codes); | ||
| 94 | } | ||
| 95 | PushResponseLanguageCode(ctx, post4_0_0_max_entries); | ||
| 96 | } | 84 | } |
| 97 | 85 | ||
| 98 | void SET::GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx) { | 86 | void SET::GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx) { |
| @@ -102,9 +90,9 @@ void SET::GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx) { | |||
| 102 | } | 90 | } |
| 103 | 91 | ||
| 104 | void SET::GetAvailableLanguageCodeCount2(Kernel::HLERequestContext& ctx) { | 92 | void SET::GetAvailableLanguageCodeCount2(Kernel::HLERequestContext& ctx) { |
| 105 | PushResponseLanguageCode(ctx, post4_0_0_max_entries); | ||
| 106 | |||
| 107 | LOG_DEBUG(Service_SET, "called"); | 93 | LOG_DEBUG(Service_SET, "called"); |
| 94 | |||
| 95 | PushResponseLanguageCode(ctx, post4_0_0_max_entries); | ||
| 108 | } | 96 | } |
| 109 | 97 | ||
| 110 | void SET::GetLanguageCode(Kernel::HLERequestContext& ctx) { | 98 | void SET::GetLanguageCode(Kernel::HLERequestContext& ctx) { |