From 49cd6f95ee88e0b37efb9d5e9d03f0a5277f3e36 Mon Sep 17 00:00:00 2001 From: Medha Tiwari Date: Mon, 31 Aug 2026 17:27:25 +0530 Subject: [PATCH] Fix WriteCompressedInt32 endianness on big-endian hosts --- Mono.Cecil.PE/ByteBuffer.cs | 6 ++++-- Test/Mono.Cecil.Tests/ByteBufferTests.cs | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git dotnet/src/cecil/Mono.Cecil.PE/ByteBuffer.cs dotnet/src/cecil/Mono.Cecil.PE/ByteBuffer.cs index 68668f53e..18f6da13f 100644 --- dotnet/src/cecil/Mono.Cecil.PE/ByteBuffer.cs +++ dotnet/src/cecil/Mono.Cecil.PE/ByteBuffer.cs @@ -269,11 +269,13 @@ public void WriteCompressedInt32 (int value) } else if ((value & ~b13) == (signMask & ~b13)) { int n = ((value & b13) << 1) | (signMask & 1); ushort val = (ushort)(0x8000 | n); - WriteUInt16 (BitConverter.IsLittleEndian ? ReverseEndianness (val) : val); + // WriteUInt16 is always little-endian; compressed ints must be big-endian. + WriteUInt16 (ReverseEndianness (val)); } else if ((value & ~b28) == (signMask & ~b28)) { int n = ((value & b28) << 1) | (signMask & 1); uint val = 0xc0000000 | (uint)n; - WriteUInt32 (BitConverter.IsLittleEndian ? ReverseEndianness (val) : val); + // WriteUInt32 is always little-endian; compressed ints must be big-endian. + WriteUInt32 (ReverseEndianness (val)); } else { throw new ArgumentOutOfRangeException ("value", "valid range is -2^28 to 2^28 -1"); } diff --git dotnet/src/cecil/Test/Mono.Cecil.Tests/ByteBufferTests.cs dotnet/src/cecil/Test/Mono.Cecil.Tests/ByteBufferTests.cs index 0c079aa97..1e5b4c68f 100644 --- dotnet/src/cecil/Test/Mono.Cecil.Tests/ByteBufferTests.cs +++ dotnet/src/cecil/Test/Mono.Cecil.Tests/ByteBufferTests.cs @@ -13,6 +13,24 @@ public void TestLargeIntegerCompressed () Assert.AreEqual (-9076, result); } + // Round-trip tests pass on big-endian even with swapped bytes. + // Assert the ECMA-335 II.23.2 encoding (always big-endian in the blob). + [Test] + public void CompressedInt32BytesAreBigEndian () + { + AssertCompressedInt32Bytes (-100, 0xBF, 0x39); + AssertCompressedInt32Bytes (-9076, 0xDF, 0xFF, 0xB9, 0x19); + } + + static void AssertCompressedInt32Bytes (int value, params byte [] expected) + { + var testee = new ByteBuffer (); + testee.WriteCompressedInt32 (value); + Assert.AreEqual (expected.Length, testee.length); + for (int i = 0; i < expected.Length; i++) + Assert.AreEqual (expected [i], testee.buffer [i]); + } + // Round-trips WriteCompressedInt32/ReadCompressedInt32 across every encoding-width // boundary of the ECMA-335 compressed signed integer format (1/2/4-byte forms) [TestCase (0)]