From dfb43927ada2d74fa35d2a2e509a3ed6567c38f7 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 3 Sep 2026 03:01:07 +1000 Subject: [PATCH] Use standard HEIF ownership arrays --- HEIF_IMPLEMENTATION_PLAN.md | 1 + src/ImageSharp/Formats/Heif/Av1/Av1CodecConfiguration.cs | 2 +- src/ImageSharp/Formats/Heif/HeifDecoderCore.cs | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/HEIF_IMPLEMENTATION_PLAN.md b/HEIF_IMPLEMENTATION_PLAN.md index f5a894231e..fd440ef065 100644 --- a/HEIF_IMPLEMENTATION_PLAN.md +++ b/HEIF_IMPLEMENTATION_PLAN.md @@ -71,6 +71,7 @@ Current cICP failure correction evidence from 2026-08-31: - The direct embedded-ICC case and every row of the 12-case profile matrix passed: 13 of 13 net11.0 Release cases. - The exact 34 cases reported by CI passed: 34 of 34 net11.0 Release cases, with zero failures and zero skips. - Roslynk reported zero compiler errors after the fix, and `git diff --check` passed. +- The remaining four branch-introduced `GC.AllocateUninitializedArray` calls are removed from AV1 configuration, pixel-information, XMP, and Exif ownership boundaries. Each retained value still receives exactly one array and one copy because its source span belongs to pooled storage; no second materialization was introduced. The exact net11 Release rebuild remains at 1,005 warnings and zero errors, 166 focused configuration and metadata cases pass, and all 9,181 HEIF tests pass through direct VSTest. Recovered task-history evidence from 2026-08-31: diff --git a/src/ImageSharp/Formats/Heif/Av1/Av1CodecConfiguration.cs b/src/ImageSharp/Formats/Heif/Av1/Av1CodecConfiguration.cs index 87c2660d97..c1fa28592b 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Av1CodecConfiguration.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Av1CodecConfiguration.cs @@ -109,7 +109,7 @@ internal sealed class Av1CodecConfiguration { // The property-reader span is pooled and reused. Retain only the sequence-header bytes required for // item/sample equivalence instead of materializing every optional configuration OBU. - this.configSequenceHeader = GC.AllocateUninitializedArray(configSequenceHeaderLength); + this.configSequenceHeader = new byte[configSequenceHeaderLength]; configObus.Slice(configSequenceHeaderOffset, configSequenceHeaderLength).CopyTo(this.configSequenceHeader); } } diff --git a/src/ImageSharp/Formats/Heif/HeifDecoderCore.cs b/src/ImageSharp/Formats/Heif/HeifDecoderCore.cs index f8b8a4a93f..574294dfdf 100644 --- a/src/ImageSharp/Formats/Heif/HeifDecoderCore.cs +++ b/src/ImageSharp/Formats/Heif/HeifDecoderCore.cs @@ -1370,7 +1370,7 @@ internal sealed class HeifDecoderCore : ImageDecoderCore // Property associations are resolved after the pooled box buffer is reused, so retain the // exact channel vector once at this ownership boundary. - byte[] channelBitDepths = GC.AllocateUninitializedArray(channelCount); + byte[] channelBitDepths = new byte[channelCount]; boxBuffer.Slice(offset, channelCount).CopyTo(channelBitDepths); for (int i = 0; i < channelBitDepths.Length; i++) { @@ -2530,7 +2530,7 @@ internal sealed class HeifDecoderCore : ImageDecoderCore Span itemData = itemMemory.GetSpan(); // XmpProfile retains its input array after the assembled item buffer is returned to its pool. - byte[] ownedData = GC.AllocateUninitializedArray(itemData.Length); + byte[] ownedData = new byte[itemData.Length]; itemData.CopyTo(ownedData); metadata.XmpProfile = new XmpProfile(ownedData); }); @@ -2583,7 +2583,7 @@ internal sealed class HeifDecoderCore : ImageDecoderCore ReadOnlySpan tiffData = exifData[actualTiffHeaderOffset..]; // ExifProfile retains its input array after the assembled item buffers are disposed at the end of decode. - byte[] ownedData = GC.AllocateUninitializedArray(tiffData.Length); + byte[] ownedData = new byte[tiffData.Length]; tiffData.CopyTo(ownedData); metadata.ExifProfile = new ExifProfile(ownedData); }