From 695911dd6f39d54a62f5ec735641c8192e6fd928 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Tue, 16 Mar 2021 10:32:54 +0100 Subject: [PATCH] Big-endian test case fixes: System.Reflection * Fix endian assumptions in tests operating on PE headers / IL metadata (this is always encoded in little-endian byte order) * Fix expected result for BlobReader test (always little-endian) * Fix expected results for GUID tests --- .../tests/ILGenerator/EmitMethodInfo.cs | 3 +- .../tests/Metadata/BlobContentIdTests.cs | 6 +- .../Ecma335/MetadataAggregatorTests.cs | 56 +++++++++--------- .../tests/Metadata/MetadataReaderTests.cs | 58 +++++++++++-------- .../tests/Metadata/TagToTokenTests.cs | 18 +++++- .../tests/Utilities/BlobReaderTests.cs | 2 +- 6 files changed, 83 insertions(+), 60 deletions(-) diff --git a/src/libraries/System.Reflection.Emit.ILGeneration/tests/ILGenerator/EmitMethodInfo.cs b/src/libraries/System.Reflection.Emit.ILGeneration/tests/ILGenerator/EmitMethodInfo.cs index 438b24b2e4ba09..3940c1559b8040 100644 --- a/src/libraries/System.Reflection.Emit.ILGeneration/tests/ILGenerator/EmitMethodInfo.cs +++ b/src/libraries/System.Reflection.Emit.ILGeneration/tests/ILGenerator/EmitMethodInfo.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Buffers.Binary; using System.Collections.Generic; using System.Linq; using System.Text; @@ -38,7 +39,7 @@ public void EmitMethodInfo() MethodInfo genMethod = type.GetMethod("Get"); byte[] il = genMethod.GetMethodBody().GetILAsByteArray(); - int ilMethodMetadataToken = BitConverter.ToInt32(il, 1); + int ilMethodMetadataToken = BinaryPrimitives.ReadInt32LittleEndian(new Span(il, 1, 4)); MethodBase resolvedMethod = type.Module.ResolveMethod(ilMethodMetadataToken); Assert.Equal(method, resolvedMethod); var methodBase = (MethodBase)genMethod.Invoke(null, null); diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/BlobContentIdTests.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/BlobContentIdTests.cs index 8e9d1df26a66a0..f6c58e74517fdf 100644 --- a/src/libraries/System.Reflection.Metadata/tests/Metadata/BlobContentIdTests.cs +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/BlobContentIdTests.cs @@ -64,17 +64,17 @@ public void FromHash() 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)); AssertEx.Equal(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x48, 0x89, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 }, id1.Guid.ToByteArray()); - AssertEx.Equal(new byte[] { 0x11, 0x12, 0x13, 0x94 }, BitConverter.GetBytes(id1.Stamp)); + Assert.Equal(0x94131211u, id1.Stamp); var id2 = BlobContentId.FromHash(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }); AssertEx.Equal(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, id2.Guid.ToByteArray()); - AssertEx.Equal(new byte[] { 0x00, 0x00, 0x00, 0x80 }, BitConverter.GetBytes(id2.Stamp)); + Assert.Equal(0x80000000u, id2.Stamp); var id3 = BlobContentId.FromHash(new byte[] { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }); AssertEx.Equal(new byte[] { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4f, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, id3.Guid.ToByteArray()); - AssertEx.Equal(new byte[] { 0xff, 0xff, 0xff, 0xff }, BitConverter.GetBytes(id3.Stamp)); + Assert.Equal(0xffffffffu, id3.Stamp); Assert.Throws(() => BlobContentId.FromHash(default(ImmutableArray))); Assert.Throws(() => BlobContentId.FromHash(null)); diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/Ecma335/MetadataAggregatorTests.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/Ecma335/MetadataAggregatorTests.cs index 03285f9e04c3f8..6d52f318fd7439 100644 --- a/src/libraries/System.Reflection.Metadata/tests/Metadata/Ecma335/MetadataAggregatorTests.cs +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/Ecma335/MetadataAggregatorTests.cs @@ -10,14 +10,14 @@ namespace System.Reflection.Metadata.Ecma335.Tests { public class MetadataAggregatorTests { - private static unsafe EnCMapTableReader CreateEncMapTable(int[] tokens) + private static unsafe EnCMapTableReader CreateEncMapTable(byte[] tokens) { GCHandle handle = GCHandle.Alloc(tokens, GCHandleType.Pinned); - var block = new MemoryBlock((byte*)handle.AddrOfPinnedObject(), tokens.Length * sizeof(uint)); - return new EnCMapTableReader(tokens.Length, block, containingBlockOffset: 0); + var block = new MemoryBlock((byte*)handle.AddrOfPinnedObject(), tokens.Length); + return new EnCMapTableReader(tokens.Length / sizeof(uint), block, containingBlockOffset: 0); } - private static EnCMapTableReader[] CreateEncMapTables(int[][] tables) + private static EnCMapTableReader[] CreateEncMapTables(byte[][] tables) { var result = new EnCMapTableReader[tables.Length]; @@ -47,35 +47,35 @@ public void RowCounts() { var encMaps = new[] { - new[] // Gen1 + new byte[] // Gen1 { - 0x0100009c, - 0x0200002e, - 0x0600009e, - 0x0600009f, - 0x23000011, + 0x9c, 0x00, 0x00, 0x01, + 0x2e, 0x00, 0x00, 0x02, + 0x9e, 0x00, 0x00, 0x06, + 0x9f, 0x00, 0x00, 0x06, + 0x11, 0x00, 0x00, 0x23, }, - new[] // Gen2 + new byte[] // Gen2 { - 0x0100009d, - 0x06000075, - 0x1700001a, - 0x18000037, - 0x18000038, - 0x23000012, - 0x23000013, + 0x9d, 0x00, 0x00, 0x01, + 0x75, 0x00, 0x00, 0x06, + 0x1a, 0x00, 0x00, 0x17, + 0x37, 0x00, 0x00, 0x18, + 0x38, 0x00, 0x00, 0x18, + 0x12, 0x00, 0x00, 0x23, + 0x13, 0x00, 0x00, 0x23, }, - new[] // Gen3 + new byte[] // Gen3 { - 0x0100009e, - 0x0100009f, - 0x06000075, - 0x11000031, - 0x1700001a, - 0x18000039, - 0x1800003a, - 0x23000014, - 0x23000015, + 0x9e, 0x00, 0x00, 0x01, + 0x9f, 0x00, 0x00, 0x01, + 0x75, 0x00, 0x00, 0x06, + 0x31, 0x00, 0x00, 0x11, + 0x1a, 0x00, 0x00, 0x17, + 0x39, 0x00, 0x00, 0x18, + 0x3a, 0x00, 0x00, 0x18, + 0x14, 0x00, 0x00, 0x23, + 0x15, 0x00, 0x00, 0x23, } }; diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs index 06fa451038fd96..bba7976b646dfa 100644 --- a/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.cs +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/MetadataReaderTests.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.IO; using System.Linq; @@ -203,11 +204,11 @@ public unsafe void InvalidExternalTableMask() byte[] peImage = (byte[])PortablePdbs.DocumentsPdb.Clone(); GCHandle pinned = GetPinnedPEImage(peImage); - //38654710855 is the external table mask from PortablePdbs.DocumentsPdb - int externalTableMaskIndex = IndexOf(peImage, BitConverter.GetBytes(38654710855), 0); + //0x900001447 is the external table mask from PortablePdbs.DocumentsPdb + int externalTableMaskIndex = IndexOf(peImage, new byte[] { 0x47, 0x14, 0, 0, 9, 0, 0, 0 }, 0); Assert.NotEqual(externalTableMaskIndex, -1); - Array.Copy(BitConverter.GetBytes(38654710855 + 1), 0, peImage, externalTableMaskIndex, BitConverter.GetBytes(38654710855 + 1).Length); + Array.Copy(new byte[] { 0x48, 0x14, 0, 0, 9, 0, 0, 0 }, 0, peImage, externalTableMaskIndex, 8); Assert.Throws(() => new MetadataReader((byte*)pinned.AddrOfPinnedObject(), peImage.Length)); } @@ -245,30 +246,30 @@ public unsafe void InvalidMetaDataTableHeaders() GCHandle pinned = GetPinnedPEImage(peImage); PEHeaders headers = new PEHeaders(new MemoryStream(peImage)); - //1392 is the remaining bytes from NetModule.AppCS - int remainingBytesIndex = IndexOf(peImage, BitConverter.GetBytes(1392), headers.MetadataStartOffset); + //0x0570 is the remaining bytes from NetModule.AppCS + int remainingBytesIndex = IndexOf(peImage, new byte[] { 0x70, 0x05, 0, 0 }, headers.MetadataStartOffset); Assert.NotEqual(remainingBytesIndex, -1); - //14057656686423 is the presentTables from NetModule.AppCS, must be after remainingBytesIndex - int presentTablesIndex = IndexOf(peImage, BitConverter.GetBytes(14057656686423), headers.MetadataStartOffset + remainingBytesIndex); + //0xcc90da21757 is the presentTables from NetModule.AppCS, must be after remainingBytesIndex + int presentTablesIndex = IndexOf(peImage, new byte[] { 0x57, 0x17, 0xa2, 0x0d, 0xc9, 0x0c, 0, 0 }, headers.MetadataStartOffset + remainingBytesIndex); Assert.NotEqual(presentTablesIndex, -1); //Set this.ModuleTable.NumberOfRows to 0 - Array.Copy(BitConverter.GetBytes((ulong)0), 0, peImage, presentTablesIndex + remainingBytesIndex + headers.MetadataStartOffset + 16, BitConverter.GetBytes((ulong)0).Length); + Array.Copy(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, peImage, presentTablesIndex + remainingBytesIndex + headers.MetadataStartOffset + 16, 8); Assert.Throws(() => new MetadataReader((byte*)pinned.AddrOfPinnedObject() + headers.MetadataStartOffset, headers.MetadataSize)); //set row counts greater than TokenTypeIds.RIDMask - Array.Copy(BitConverter.GetBytes((ulong)16777216), 0, peImage, presentTablesIndex + remainingBytesIndex + headers.MetadataStartOffset + 16, BitConverter.GetBytes((ulong)16777216).Length); + Array.Copy(new byte[] { 0, 0, 1, 0 }, 0, peImage, presentTablesIndex + remainingBytesIndex + headers.MetadataStartOffset + 16, 4); Assert.Throws(() => new MetadataReader((byte*)pinned.AddrOfPinnedObject() + headers.MetadataStartOffset, headers.MetadataSize)); //set remaining bytes smaller than required for row counts. - Array.Copy(BitConverter.GetBytes(25), 0, peImage, remainingBytesIndex + headers.MetadataStartOffset, BitConverter.GetBytes(25).Length); + Array.Copy(new byte[] { 25, 0, 0, 0 }, 0, peImage, remainingBytesIndex + headers.MetadataStartOffset, 4); Assert.Throws(() => new MetadataReader((byte*)pinned.AddrOfPinnedObject() + headers.MetadataStartOffset, headers.MetadataSize)); - //14057656686424 is a value to make (presentTables & ~validTables) != 0 but not (presentTables & (ulong)(TableMask.PtrTables | TableMask.EnCMap)) != 0 - Array.Copy(BitConverter.GetBytes((ulong)14057656686424), 0, peImage, presentTablesIndex + remainingBytesIndex + headers.MetadataStartOffset, BitConverter.GetBytes((ulong)14057656686424).Length); + //0xcc90da21758 is a value to make (presentTables & ~validTables) != 0 but not (presentTables & (ulong)(TableMask.PtrTables | TableMask.EnCMap)) != 0 + Array.Copy(new byte[] { 0x58, 0x17, 0xa2, 0x0d, 0xc9, 0x0c, 0, 0 }, 0, peImage, presentTablesIndex + remainingBytesIndex + headers.MetadataStartOffset, 8); Assert.Throws(() => new MetadataReader((byte*)pinned.AddrOfPinnedObject() + headers.MetadataStartOffset, headers.MetadataSize)); - //14066246621015 makes (presentTables & ~validTables) != 0 fail - Array.Copy(BitConverter.GetBytes((ulong)14066246621015), 0, peImage, presentTablesIndex + remainingBytesIndex + headers.MetadataStartOffset, BitConverter.GetBytes((ulong)14066246621015).Length); + //0xccb0da21757 makes (presentTables & ~validTables) != 0 fail + Array.Copy(new byte[] { 0x57, 0x17, 0xa2, 0x0d, 0xcb, 0x0c, 0, 0 }, 0, peImage, presentTablesIndex + remainingBytesIndex + headers.MetadataStartOffset, 8); Assert.Throws(() => new MetadataReader((byte*)pinned.AddrOfPinnedObject() + headers.MetadataStartOffset, headers.MetadataSize)); //set remaining bytes smaller than MetadataStreamConstants.SizeOfMetadataTableHeader - Array.Copy(BitConverter.GetBytes(1), 0, peImage, remainingBytesIndex + headers.MetadataStartOffset, BitConverter.GetBytes(1).Length); + Array.Copy(new byte[] { 1, 0, 0, 0 }, 0, peImage, remainingBytesIndex + headers.MetadataStartOffset, 4); Assert.Throws(() => new MetadataReader((byte*)pinned.AddrOfPinnedObject() + headers.MetadataStartOffset, headers.MetadataSize)); } @@ -3033,18 +3034,25 @@ private static unsafe byte[] ObfuscateWithExtraData(byte[] unobfuscated, bool se Array.Copy(unobfuscated, obfuscated, offsetToModuleTable); Array.Copy(unobfuscated, offsetToModuleTable, obfuscated, offsetToModuleTable + sizeOfExtraData, unobfuscated.Length - offsetToModuleTable); - fixed (byte* ptr = obfuscated) - { - // increase size of metadata - *(int*)(ptr + offsetToMetadataSize) += sizeOfExtraData; + // increase size of metadata + Span MetadataSizeSpan = new Span(obfuscated, offsetToMetadataSize, 4); + uint MetadataSize = BinaryPrimitives.ReadUInt32LittleEndian(MetadataSizeSpan); + BinaryPrimitives.WriteUInt32LittleEndian(MetadataSizeSpan, MetadataSize + sizeOfExtraData); - // increase size of table stream - *(int*)(ptr + streamHeaders[tableStreamIndex].OffsetToSize) += sizeOfExtraData; + // increase size of table stream + Span TableStreamSpan = new Span(obfuscated, streamHeaders[tableStreamIndex].OffsetToSize, 4); + uint TableStreamSize = BinaryPrimitives.ReadUInt32LittleEndian(TableStreamSpan); + BinaryPrimitives.WriteUInt32LittleEndian(TableStreamSpan, TableStreamSize + sizeOfExtraData); - // adjust offset of any streams that follow it - for (int i = 0; i < streamHeaders.Length; i++) - if (streamHeaders[i].Offset > streamHeaders[tableStreamIndex].Offset) - *(int*)(ptr + streamHeaders[i].OffsetToOffset) += sizeOfExtraData; + // adjust offset of any streams that follow it + for (int i = 0; i < streamHeaders.Length; i++) + { + if (streamHeaders[i].Offset > streamHeaders[tableStreamIndex].Offset) + { + Span OffsetSpan = new Span(obfuscated, streamHeaders[i].OffsetToOffset, 4); + uint Offset = BinaryPrimitives.ReadUInt32LittleEndian(OffsetSpan); + BinaryPrimitives.WriteUInt32LittleEndian(OffsetSpan, Offset + sizeOfExtraData); + } } // write non-zero "extra data" to make sure so that our assertion of leading Module.Generation == 0 diff --git a/src/libraries/System.Reflection.Metadata/tests/Metadata/TagToTokenTests.cs b/src/libraries/System.Reflection.Metadata/tests/Metadata/TagToTokenTests.cs index ae9058c7ffefc7..329b6e2c1af5a2 100644 --- a/src/libraries/System.Reflection.Metadata/tests/Metadata/TagToTokenTests.cs +++ b/src/libraries/System.Reflection.Metadata/tests/Metadata/TagToTokenTests.cs @@ -61,11 +61,25 @@ private IEnumerable GetTags() Assert.Contains(vector.FieldType, new[] { typeof(uint), typeof(ulong) }); if (vector.FieldType == typeof(uint)) { - return BitConverter.GetBytes((uint)vector.GetValue(null)).Select(t => (uint)t << TokenTypeIds.RowIdBitCount).ToArray(); + uint value = (uint)vector.GetValue(null); + uint[] ret = new uint[4]; + for (uint i = 0; i < 4; i++) + { + ret[i] = ((uint)(byte)value) << TokenTypeIds.RowIdBitCount; + value >>= 8; + } + return ret; } else { - return BitConverter.GetBytes((ulong)vector.GetValue(null)).Select(t => (uint)t << TokenTypeIds.RowIdBitCount).ToArray(); + ulong value = (ulong)vector.GetValue(null); + uint[] ret = new uint[8]; + for (uint i = 0; i < 8; i++) + { + ret[i] = ((uint)(byte)value) << TokenTypeIds.RowIdBitCount; + value >>= 8; + } + return ret; } }, diff --git a/src/libraries/System.Reflection.Metadata/tests/Utilities/BlobReaderTests.cs b/src/libraries/System.Reflection.Metadata/tests/Utilities/BlobReaderTests.cs index 318c7938336514..096846d0ce49e8 100644 --- a/src/libraries/System.Reflection.Metadata/tests/Utilities/BlobReaderTests.cs +++ b/src/libraries/System.Reflection.Metadata/tests/Utilities/BlobReaderTests.cs @@ -307,7 +307,7 @@ public unsafe void ReadFromMemoryReader() reader.Reset(); Assert.Equal(0, reader.Offset); - Assert.Equal(BitConverter.ToDouble(buffer2, 0), reader.ReadDouble()); + Assert.Equal(BitConverter.Int64BitsToDouble(0x0807060504030201L), reader.ReadDouble()); } }