From 54bfaa125d9b6ae1be53ec431d40326fba51d0de Mon Sep 17 00:00:00 2001
From: Mary <mary@mary.zone>
Date: Mon, 7 Mar 2022 09:49:29 +0100
Subject: [PATCH] amadeus: Fix wrong Span usage in CopyHistories (#3181)

Fix a copypasta from the original Amadeus PR causing invalid
CopyHistories output.

Also added a missing size check.

This fix a crash in Mononoke Slashdown
---
 .../Performance/PerformanceManagerGeneric.cs       | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/Ryujinx.Audio/Renderer/Server/Performance/PerformanceManagerGeneric.cs b/Ryujinx.Audio/Renderer/Server/Performance/PerformanceManagerGeneric.cs
index b17e6f3f..4b8ec254 100644
--- a/Ryujinx.Audio/Renderer/Server/Performance/PerformanceManagerGeneric.cs
+++ b/Ryujinx.Audio/Renderer/Server/Performance/PerformanceManagerGeneric.cs
@@ -149,11 +149,21 @@ namespace Ryujinx.Audio.Renderer.Server.Performance
 
                 Span<byte> targetSpan = performanceOutput.Slice(nextOffset);
 
+                // NOTE: We check for the space for two headers for the final blank header.
+                int requiredSpace = Unsafe.SizeOf<THeader>() + Unsafe.SizeOf<TEntry>() * inputHeader.GetEntryCount()
+                                                             + Unsafe.SizeOf<TEntryDetail>() * inputHeader.GetEntryDetailCount()
+                                                             + Unsafe.SizeOf<THeader>();
+
+                if (targetSpan.Length < requiredSpace)
+                {
+                    break;
+                }
+
                 ref THeader outputHeader = ref MemoryMarshal.Cast<byte, THeader>(targetSpan)[0];
 
                 nextOffset += Unsafe.SizeOf<THeader>();
 
-                Span<TEntry> outputEntries = MemoryMarshal.Cast<byte, TEntry>(targetSpan.Slice(nextOffset));
+                Span<TEntry> outputEntries = MemoryMarshal.Cast<byte, TEntry>(performanceOutput.Slice(nextOffset));
 
                 int totalProcessingTime = 0;
 
@@ -175,7 +185,7 @@ namespace Ryujinx.Audio.Renderer.Server.Performance
                     }
                 }
 
-                Span<TEntryDetail> outputEntriesDetail = MemoryMarshal.Cast<byte, TEntryDetail>(targetSpan.Slice(nextOffset));
+                Span<TEntryDetail> outputEntriesDetail = MemoryMarshal.Cast<byte, TEntryDetail>(performanceOutput.Slice(nextOffset));
 
                 int effectiveEntryDetailCount = 0;