diff --git a/src/xenia/kernel/xenumerator.cc b/src/xenia/kernel/xenumerator.cc index fc21e483a..e55b4200c 100644 --- a/src/xenia/kernel/xenumerator.cc +++ b/src/xenia/kernel/xenumerator.cc @@ -62,19 +62,28 @@ uint8_t* XStaticUntypedEnumerator::AppendItem() { uint32_t XStaticUntypedEnumerator::WriteItems(uint8_t* buffer_data, uint32_t buffer_size, uint32_t* written_count) { - size_t count = std::min(item_count_ - current_item_, items_per_enumerate()); - if (!count) { + const size_t actual_count = + std::min(item_count_ - current_item_, items_per_enumerate()); + if (!actual_count) { return X_ERROR_NO_MORE_FILES; } - size_t size = count * item_size(); - size_t offset = current_item_ * item_size(); + // 4E4D07F0 does not respect buffer_size for XContentCreateEnumerator. + assert_false(buffer_size < item_size()); + + const size_t available_count = buffer_size / item_size(); + const size_t size = actual_count * item_size(); + const size_t offset = current_item_ * item_size(); + + // Some enumerators expect buffer_size to be respected for now assert. + assert_false(actual_count > available_count); + std::memcpy(buffer_data, buffer_.data() + offset, size); - current_item_ += count; + current_item_ += actual_count; if (written_count) { - *written_count = static_cast(count); + *written_count = static_cast(actual_count); } return X_ERROR_SUCCESS; @@ -83,19 +92,24 @@ uint32_t XStaticUntypedEnumerator::WriteItems(uint8_t* buffer_data, uint32_t XAchievementEnumerator::WriteItems(uint8_t* buffer_data, uint32_t buffer_size, uint32_t* written_count) { - if (items_.size() - current_item_ <= 0) { + const size_t actual_count = + std::min(items_.size() - current_item_, items_per_enumerate()); + if (!actual_count) { return X_ERROR_NO_MORE_FILES; } - const size_t count = - std::min(items_.size() - current_item_, items_per_enumerate()); + const size_t available_count = buffer_size / item_size(); + + // Unknown if buffer_size should be respected. + assert_false(actual_count > available_count); + auto details = reinterpret_cast(buffer_data); size_t string_offset = items_per_enumerate() * sizeof(xam::X_ACHIEVEMENT_DETAILS); - auto string_buffer = - StringBuffer{&buffer_data[string_offset], - count * xam::X_ACHIEVEMENT_DETAILS::kStringBufferSize}; - for (size_t i = 0; i < count; ++i, ++current_item_) { + auto string_buffer = StringBuffer{ + &buffer_data[string_offset], + actual_count * xam::X_ACHIEVEMENT_DETAILS::kStringBufferSize}; + for (size_t i = 0; i < actual_count; ++i, ++current_item_) { const auto& item = items_[current_item_]; details[i].id = item.id; details[i].label_ptr = @@ -112,7 +126,7 @@ uint32_t XAchievementEnumerator::WriteItems(uint8_t* buffer_data, } if (written_count) { - *written_count = static_cast(count); + *written_count = static_cast(actual_count); } return X_ERROR_SUCCESS; @@ -121,15 +135,20 @@ uint32_t XAchievementEnumerator::WriteItems(uint8_t* buffer_data, uint32_t XTitleEnumerator::WriteItems(uint8_t* buffer_data, uint32_t buffer_size, uint32_t* written_count) { - size_t count = std::min(items_.size() - current_item_, items_per_enumerate()); - if (!count) { + const size_t actual_count = + std::min(items_.size() - current_item_, items_per_enumerate()); + if (!actual_count) { return X_ERROR_NO_MORE_FILES; } - size_t size = count * item_size(); + const size_t available_count = buffer_size / item_size(); + + // Unknown if buffer_size should be respected. + assert_false(actual_count > available_count); + auto details = reinterpret_cast(buffer_data); - for (size_t i = 0; i < count; ++i, ++current_item_) { + for (size_t i = 0; i < actual_count; ++i, ++current_item_) { const auto& item = items_[current_item_]; details[i].base.title_id = item.id; details[i].base.achievements_count = item.achievements_count; @@ -157,7 +176,7 @@ uint32_t XTitleEnumerator::WriteItems(uint8_t* buffer_data, } if (written_count) { - *written_count = static_cast(count); + *written_count = static_cast(actual_count); } return X_ERROR_SUCCESS; @@ -182,18 +201,22 @@ uint32_t XMPCreateUserPlaylistEnumerator::WriteItems(uint8_t* buffer_data, // Fixed 545408C0 freezing at main menu. std::memset(buffer_data, 0, buffer_size); - size_t count = std::min(items_.size() - current_item_, items_per_enumerate()); - if (!count) { + const size_t actual_count = + std::min(items_.size() - current_item_, items_per_enumerate()); + if (!actual_count) { return X_ERROR_NO_MORE_FILES; } + const size_t available_count = buffer_size / item_size(); + const size_t valid_count = std::min(actual_count, available_count); + xam::XMP_USER_PLAYLIST_INFO* results = reinterpret_cast(buffer_data); - std::copy_n(items_.begin() + current_item_, count, results); + std::copy_n(items_.begin() + current_item_, valid_count, results); if (written_count) { - *written_count = static_cast(count); + *written_count = static_cast(valid_count); } return X_ERROR_SUCCESS;