diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/Handles.TypeSystem.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/Handles.TypeSystem.cs index 5d610fed99e949..e2de1c221e8d19 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/Handles.TypeSystem.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/Handles.TypeSystem.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Buffers.Binary; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Reflection.Metadata.Ecma335; @@ -2591,14 +2592,11 @@ internal static BlobHandle FromVirtualIndex(VirtualIndex virtualIndex, ushort vi internal const int TemplateParameterOffset_AttributeUsageTarget = 2; - internal unsafe void SubstituteTemplateParameters(byte[] blob) + internal void SubstituteTemplateParameters(byte[] blob) { Debug.Assert(blob.Length >= TemplateParameterOffset_AttributeUsageTarget + 4); - fixed (byte* ptr = &blob[TemplateParameterOffset_AttributeUsageTarget]) - { - *((uint*)ptr) = VirtualValue; - } + BinaryPrimitives.WriteUInt32LittleEndian(blob.AsSpan(TemplateParameterOffset_AttributeUsageTarget), VirtualValue); } public static implicit operator Handle(BlobHandle handle) diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEBuilder.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEBuilder.cs index 8389ff7359c1b0..73107af667990a 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEBuilder.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEBuilder.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Buffers.Binary; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; @@ -467,23 +468,6 @@ internal static IEnumerable GetContentToSign(BlobBuilder peImage, int peHe internal static Blob GetPrefixBlob(Blob container, Blob blob) => new Blob(container.Buffer, container.Start, blob.Start - container.Start); internal static Blob GetSuffixBlob(Blob container, Blob blob) => new Blob(container.Buffer, blob.Start + blob.Length, container.Start + container.Length - blob.Start - blob.Length); - // internal for testing - internal static IEnumerable GetContentToChecksum(BlobBuilder peImage, Blob checksumFixup) - { - foreach (var blob in peImage.GetBlobs()) - { - if (blob.Buffer == checksumFixup.Buffer) - { - yield return GetPrefixBlob(blob, checksumFixup); - yield return GetSuffixBlob(blob, checksumFixup); - } - else - { - yield return blob; - } - } - } - internal void Sign(BlobBuilder peImage, Blob strongNameSignatureFixup, Func, byte[]> signatureProvider) { Debug.Assert(peImage != null); @@ -508,57 +492,56 @@ internal void Sign(BlobBuilder peImage, Blob strongNameSignatureFixup, Func blobs) { uint checksum = 0; int pendingByte = -1; - foreach (var blob in blobs) + foreach (Blob blob in peImage.GetBlobs()) { - var segment = blob.GetBytes(); - fixed (byte* arrayPtr = segment.Array) + if (blob.Buffer == checksumFixup.Buffer) { - Debug.Assert(segment.Count > 0); - - byte* ptr = arrayPtr + segment.Offset; - byte* end = ptr + segment.Count; + // The checksum field itself is excluded, so checksum the content before and + // after the fixup as two separate segments. + AddToChecksum(GetPrefixBlob(blob, checksumFixup).GetBytes(), ref checksum, ref pendingByte); + AddToChecksum(GetSuffixBlob(blob, checksumFixup).GetBytes(), ref checksum, ref pendingByte); + } + else + { + AddToChecksum(blob.GetBytes(), ref checksum, ref pendingByte); + } + } - if (pendingByte >= 0) - { - // little-endian encoding: - checksum = AggregateChecksum(checksum, (ushort)(*ptr << 8 | pendingByte)); - ptr++; - } + if (pendingByte >= 0) + { + checksum = AggregateChecksum(checksum, (ushort)pendingByte); + } - if ((end - ptr) % 2 != 0) - { - end--; - pendingByte = *end; - } - else - { - pendingByte = -1; - } + return checksum + (uint)peImage.Count; + } - while (ptr < end) - { - // little-endian encoding: - checksum = AggregateChecksum(checksum, (ushort)(ptr[1] << 8 | ptr[0])); - ptr += sizeof(ushort); - } - } + private static void AddToChecksum(ReadOnlySpan segment, ref uint checksum, ref int pendingByte) + { + if (segment.IsEmpty) + { + return; } if (pendingByte >= 0) { - checksum = AggregateChecksum(checksum, (ushort)pendingByte); + // little-endian encoding: + checksum = AggregateChecksum(checksum, (ushort)(segment[0] << 8 | pendingByte)); + segment = segment.Slice(1); + } + + while (segment.Length >= sizeof(ushort)) + { + // little-endian encoding: + checksum = AggregateChecksum(checksum, BinaryPrimitives.ReadUInt16LittleEndian(segment)); + segment = segment.Slice(sizeof(ushort)); } - return checksum; + // Carry a trailing odd byte over to the next segment. + pendingByte = segment.IsEmpty ? -1 : segment[0]; } private static uint AggregateChecksum(uint checksum, ushort value)