From 96115916b237bd1b96b42ce79cb0904f35eb697b Mon Sep 17 00:00:00 2001 From: Kurt Date: Sat, 22 May 2021 09:27:46 -0700 Subject: [PATCH] Prevent overflow of memo write Setting too many invalid entries will bloat above 500, so clamp the max. Preallocate entries size rather than 4 always --- .../Saves/Substructures/Gen3/StrategyMemo.cs | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/PKHeX.Core/Saves/Substructures/Gen3/StrategyMemo.cs b/PKHeX.Core/Saves/Substructures/Gen3/StrategyMemo.cs index 461fc060d..cd8a2ee24 100644 --- a/PKHeX.Core/Saves/Substructures/Gen3/StrategyMemo.cs +++ b/PKHeX.Core/Saves/Substructures/Gen3/StrategyMemo.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; namespace PKHeX.Core { @@ -8,13 +7,12 @@ public sealed class StrategyMemo { private readonly bool XD; public const int SIZE_ENTRY = 12; - private readonly List Entries = new(); + private readonly List Entries; public const int MAX_COUNT = 500; - public const int MAX_SIZE = MAX_COUNT * SIZE_ENTRY; private StrategyMemoEntry? this[int Species] => Entries.Find(e => e.Species == Species); - private readonly byte[] _unk; + private readonly ushort _unk; - public StrategyMemo(bool xd = true) : this(new byte[MAX_SIZE], 0, xd) { } + public StrategyMemo(bool xd = true) : this(new byte[4], 0, xd) { } public StrategyMemo(byte[] input, int offset, bool xd) { @@ -22,7 +20,9 @@ public StrategyMemo(byte[] input, int offset, bool xd) int count = BigEndian.ToInt16(input, offset); if (count > MAX_COUNT) count = MAX_COUNT; - _unk = input.Slice(offset + 2, 2); + _unk = BigEndian.ToUInt16(input, offset + 2); + + Entries = new List(count); for (int i = 0; i < count; i++) { var entry = Read(input, offset, i); @@ -38,8 +38,17 @@ private StrategyMemoEntry Read(byte[] input, int offset, int index) return new StrategyMemoEntry(XD, data); } - public byte[] Write() => BigEndian.GetBytes((short)Entries.Count).Concat(_unk) // count followed by populated entries - .Concat(Entries.SelectMany(entry => entry.Data)).ToArray(); + public byte[] Write() + { + var result = new byte[4 + (Entries.Count * SIZE_ENTRY)]; + BigEndian.GetBytes((short)Entries.Count).CopyTo(result, 0); + BigEndian.GetBytes((short)_unk).CopyTo(result, 2); + + var count = Math.Min(MAX_COUNT, Entries.Count); + for (int i = 0; i < count; i++) + Entries[i].Data.CopyTo(result, 4 + (i * SIZE_ENTRY)); + return result; + } public StrategyMemoEntry GetEntry(int Species) {