public unsafe void DefaultDecodingFallbackMatchesBcl() { byte[] buffer; int bytesRead; var decoder = MetadataStringDecoder.DefaultUTF8; // dangling lead byte fixed (byte* ptr = (buffer = new byte[] { 0xC0 })) { string s = new MemoryBlock(ptr, buffer.Length).PeekUtf8NullTerminated(0, null, decoder, out bytesRead); Assert.Equal("\uFFFD", new MemoryBlock(ptr, buffer.Length).PeekUtf8NullTerminated(0, null, decoder, out bytesRead)); Assert.Equal(s, Encoding.UTF8.GetString(buffer)); Assert.Equal(buffer.Length, bytesRead); s = new MemoryBlock(ptr, buffer.Length).PeekUtf8NullTerminated(0, Encoding.UTF8.GetBytes("Hello"), decoder, out bytesRead); Assert.Equal("Hello\uFFFD", s); Assert.Equal(s, "Hello" + Encoding.UTF8.GetString(buffer)); Assert.Equal(buffer.Length, bytesRead); Assert.Equal("\uFFFD", new MemoryBlock(ptr, buffer.Length).PeekUtf8(0, buffer.Length)); } // overlong encoding fixed (byte* ptr = (buffer = new byte[] { (byte)'a', 0xC0, 0xAF, (byte)'b', 0x0 })) { var block = new MemoryBlock(ptr, buffer.Length); Assert.Equal("a\uFFFD\uFFFDb", block.PeekUtf8NullTerminated(0, null, decoder, out bytesRead)); Assert.Equal(buffer.Length, bytesRead); } // TODO: There are a bunch more error cases of course, but this is enough to break the old code // and we now just call the BCL, so from a white box perspective, we needn't get carried away. }
public unsafe void ReadFromMemoryBlock() { byte[] buffer = new byte[4] { 0, 1, 0, 2 }; fixed (byte* bufferPtr = buffer) { var block = new MemoryBlock(bufferPtr, buffer.Length); Assert.Throws<BadImageFormatException>(() => block.PeekUInt32(Int32.MaxValue)); Assert.Throws<BadImageFormatException>(() => block.PeekUInt32(-1)); Assert.Throws<BadImageFormatException>(() => block.PeekUInt32(Int32.MinValue)); Assert.Throws<BadImageFormatException>(() => block.PeekUInt32(4)); Assert.Throws<BadImageFormatException>(() => block.PeekUInt32(1)); Assert.Equal(0x02000100U, block.PeekUInt32(0)); Assert.Throws<BadImageFormatException>(() => block.PeekUInt16(Int32.MaxValue)); Assert.Throws<BadImageFormatException>(() => block.PeekUInt16(-1)); Assert.Throws<BadImageFormatException>(() => block.PeekUInt16(Int32.MinValue)); Assert.Throws<BadImageFormatException>(() => block.PeekUInt16(4)); Assert.Equal(0x0200, block.PeekUInt16(2)); int bytesRead; MetadataStringDecoder stringDecoder = MetadataStringDecoder.DefaultUTF8; Assert.Throws<BadImageFormatException>(() => block.PeekUtf8NullTerminated(Int32.MaxValue, null, stringDecoder, out bytesRead)); Assert.Throws<BadImageFormatException>(() => block.PeekUtf8NullTerminated(-1, null, stringDecoder, out bytesRead)); Assert.Throws<BadImageFormatException>(() => block.PeekUtf8NullTerminated(Int32.MinValue, null, stringDecoder, out bytesRead)); Assert.Throws<BadImageFormatException>(() => block.PeekUtf8NullTerminated(5, null, stringDecoder, out bytesRead)); Assert.Throws<BadImageFormatException>(() => block.GetMemoryBlockAt(-1, 1)); Assert.Throws<BadImageFormatException>(() => block.GetMemoryBlockAt(1, -1)); Assert.Throws<BadImageFormatException>(() => block.GetMemoryBlockAt(0, -1)); Assert.Throws<BadImageFormatException>(() => block.GetMemoryBlockAt(-1, 0)); Assert.Throws<BadImageFormatException>(() => block.GetMemoryBlockAt(-Int32.MaxValue, Int32.MaxValue)); Assert.Throws<BadImageFormatException>(() => block.GetMemoryBlockAt(Int32.MaxValue, -Int32.MaxValue)); Assert.Throws<BadImageFormatException>(() => block.GetMemoryBlockAt(Int32.MaxValue, Int32.MaxValue)); Assert.Throws<BadImageFormatException>(() => block.GetMemoryBlockAt(block.Length, -1)); Assert.Throws<BadImageFormatException>(() => block.GetMemoryBlockAt(-1, block.Length)); Assert.Equal("\u0001", block.PeekUtf8NullTerminated(1, null, stringDecoder, out bytesRead)); Assert.Equal(bytesRead, 2); Assert.Equal("\u0002", block.PeekUtf8NullTerminated(3, null, stringDecoder, out bytesRead)); Assert.Equal(bytesRead, 1); Assert.Equal("", block.PeekUtf8NullTerminated(4, null, stringDecoder, out bytesRead)); Assert.Equal(bytesRead, 0); byte[] helloPrefix = Encoding.UTF8.GetBytes("Hello"); Assert.Equal("Hello\u0001", block.PeekUtf8NullTerminated(1, helloPrefix, stringDecoder, out bytesRead)); Assert.Equal(bytesRead, 2); Assert.Equal("Hello\u0002", block.PeekUtf8NullTerminated(3, helloPrefix, stringDecoder, out bytesRead)); Assert.Equal(bytesRead, 1); Assert.Equal("Hello", block.PeekUtf8NullTerminated(4, helloPrefix, stringDecoder, out bytesRead)); Assert.Equal(bytesRead, 0); } }