From a0328c8330816b5ebff6160697aaa6b1ec3bada4 Mon Sep 17 00:00:00 2001 From: Kurt Date: Mon, 1 Jun 2026 22:25:34 -0500 Subject: [PATCH] Misc tweaks Minor internal api safety to avoid potential memory leaks --- PKHeX.Core/Saves/SAV4HGSS.cs | 13 ++++-------- PKHeX.Drawing/ImageUtil.cs | 39 +++++++++++++++++------------------- 2 files changed, 22 insertions(+), 30 deletions(-) diff --git a/PKHeX.Core/Saves/SAV4HGSS.cs b/PKHeX.Core/Saves/SAV4HGSS.cs index c33453ab8..0a47a8764 100644 --- a/PKHeX.Core/Saves/SAV4HGSS.cs +++ b/PKHeX.Core/Saves/SAV4HGSS.cs @@ -208,27 +208,22 @@ public int Badges16 } private const int OFS_GearRolodex = 0xC0EC; - private const byte GearMaxCallers = (byte)(PokegearNumber.Ernest + 1); + private const byte GearCallerCount = (byte)(PokegearNumber.Ernest + 1); public PokegearNumber GetCallerAtIndex(int index) => (PokegearNumber)General[OFS_GearRolodex + index]; public void SetCallerAtIndex(int index, PokegearNumber caller) => General[OFS_GearRolodex + index] = (byte)caller; public Span GetPokeGearRoloDex() { - var arr = General.Slice(OFS_GearRolodex, GearMaxCallers); + var arr = General.Slice(OFS_GearRolodex, GearCallerCount); return MemoryMarshal.Cast(arr); } - public void SetPokeGearRoloDex(ReadOnlySpan value) - { - if (value.Length > GearMaxCallers) - throw new ArgumentOutOfRangeException(nameof(value)); - MemoryMarshal.AsBytes(value).CopyTo(General.Slice(OFS_GearRolodex, GearMaxCallers)); - } + public void SetPokeGearRoloDex(ReadOnlySpan value) => value.CopyTo(GetPokeGearRoloDex()); public void PokeGearUnlockAllCallers() { - for (int i = 0; i < GearMaxCallers; i++) + for (int i = 0; i < GearCallerCount; i++) SetCallerAtIndex(i, (PokegearNumber)i); } diff --git a/PKHeX.Drawing/ImageUtil.cs b/PKHeX.Drawing/ImageUtil.cs index 0bd3ca755..f8fed2c9e 100644 --- a/PKHeX.Drawing/ImageUtil.cs +++ b/PKHeX.Drawing/ImageUtil.cs @@ -32,8 +32,7 @@ public static class ImageUtil public Span GetBitmapData(out BitmapData bmpData, PixelFormat format = PixelFormat.Format32bppArgb) { bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, format); - var bpp = Image.GetPixelFormatSize(format) / 8; - return GetSpan(bmpData.Scan0, bmp.Width * bmp.Height * bpp); + return GetSpan(bmpData.Scan0, Math.Abs(bmpData.Stride) * bmpData.Height); } public void GetBitmapData(Span data, PixelFormat format = PixelFormat.Format32bppArgb) @@ -69,10 +68,9 @@ public void SetBitmapData(Span data) public byte[] GetBitmapData() { var format = bmp.PixelFormat; - var bpp = Image.GetPixelFormatSize(format) / 8; - var result = new byte[bmp.Width * bmp.Height * bpp]; - bmp.GetBitmapData(result, format); - return result; + var span = bmp.GetBitmapData(out var bmpData, format); + try { return [..span]; } + finally { bmp.UnlockBits(bmpData); } } public void ToGrayscale(float intensity) @@ -81,8 +79,8 @@ public void ToGrayscale(float intensity) return; // don't care var data = bmp.GetBitmapData(out var bmpData); - SetAllColorToGrayScale(data, intensity); - bmp.UnlockBits(bmpData); + try { SetAllColorToGrayScale(data, intensity); } + finally { bmp.UnlockBits(bmpData); } } public void ChangeOpacity(double trans) @@ -91,8 +89,8 @@ public void ChangeOpacity(double trans) return; // don't care var data = bmp.GetBitmapData(out var bmpData); - SetAllTransparencyTo(data, trans); - bmp.UnlockBits(bmpData); + try { SetAllTransparencyTo(data, trans); } + finally { bmp.UnlockBits(bmpData); } } public void BlendTransparentTo(Color c, byte trans, int start = 0, int end = -1) @@ -100,15 +98,15 @@ public void BlendTransparentTo(Color c, byte trans, int start = 0, int end = -1) var data = bmp.GetBitmapData(out var bmpData); if (end == -1) end = data.Length; - BlendAllTransparencyTo(data[start..end], c, trans); - bmp.UnlockBits(bmpData); + try { BlendAllTransparencyTo(data[start..end], c, trans); } + finally { bmp.UnlockBits(bmpData); } } public void ChangeAllColorTo(Color c) { var data = bmp.GetBitmapData(out var bmpData); - ChangeAllColorTo(data, c); - bmp.UnlockBits(bmpData); + try { ChangeAllColorTo(data, c); } + finally { bmp.UnlockBits(bmpData); } } public void ChangeTransparentTo(Color c, byte trans, int start = 0, int end = -1) @@ -116,23 +114,22 @@ public void ChangeTransparentTo(Color c, byte trans, int start = 0, int end = -1 var data = bmp.GetBitmapData(out var bmpData); if (end == -1) end = data.Length; - SetAllTransparencyTo(data[start..end], c, trans); - bmp.UnlockBits(bmpData); + try { SetAllTransparencyTo(data[start..end], c, trans); } + finally { bmp.UnlockBits(bmpData); } } public void WritePixels(Color c, int start, int end) { var data = bmp.GetBitmapData(out var bmpData); - ChangeAllTo(data, c, start, end); - bmp.UnlockBits(bmpData); + try { ChangeAllTo(data, c, start, end); } + finally { bmp.UnlockBits(bmpData); } } public int GetAverageColor() { var data = bmp.GetBitmapData(out var bmpData); - var avg = GetAverageColor(data); - bmp.UnlockBits(bmpData); - return avg; + try { return GetAverageColor(data); } + finally { bmp.UnlockBits(bmpData); } } }