解码包含LF字符的base64字节时发生IndexOutOfRangeException(仅适用于>= .NET 5)

unftdfkk  于 2023-02-17  发布在  .NET
关注(0)|答案(1)|浏览(173)

我已经将运行时从netcoreapp3.1升级到NET 5,将包含LF字符的base64字节转换为字符串的代码开始崩溃,并出现IndexOutOfRangeException。Windows和Linux平台的行为相同。
我已经有了submitted a bug report,但还是决定问一下这段代码是否有错误或容易出现bug的地方。
现在,我能想到的一个解决方案是添加一个中间件流,它将从输入中删除所有LF字符,因为无论如何,空格在base64中是过多的。值得一提的是,CRLF分隔符没有发生异常。

[TestFixture]
public class Fixture
{
    [Test]
    public void Crashes_on_runtime_greater_or_equal_to_NET_5()
    {
        var txt = "YWJj\nZGVm"; // abc\ndef
        var base64Bytes = Encoding.UTF8.GetBytes(txt);
        var stream = new MemoryStream(base64Bytes);
        var base64Transform = new FromBase64Transform();
        var cryptoStream = new CryptoStream(stream, base64Transform, CryptoStreamMode.Read);

        var result = new MemoryStream();
        cryptoStream.CopyTo(result);

        Console.WriteLine(Encoding.UTF8.GetString(result.ToArray()));
    }
}
System.IndexOutOfRangeException : Index was outside the bounds of the array.
   at System.Security.Cryptography.FromBase64Transform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
   at System.Security.Cryptography.CryptoStream.ReadAsyncCore(Memory`1 buffer, CancellationToken cancellationToken, Boolean useAsync)
   at System.Security.Cryptography.CryptoStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at System.Security.Cryptography.CryptoStream.CopyTo(Stream destination, Int32 bufferSize)
   at System.IO.Stream.CopyTo(Stream destination)
   at ClassLibrary1.Fixture.Crashes_on_runtime_greater_or_equal_to_NET_5() in E:\cm_1\drive\ClassLibrary1\Class1.cs:line 20
w41d8nur

w41d8nur1#

加密流调用:

int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, ...)

对于输入缓冲器,偏移量0,计数8(已读取两个完整块,2 * 4)。
FromBase64Transform保留一些内部状态并返回6(已写入6个字节的输出),然后接收最后一个调用:

byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)

这会触发FromBase64Transform中的bug,特别是在主动内联方法中:

private static int GetOutputSize(int bytesToTransform, Span<byte> tmpBuffer)
{
    // ...
    if (tmpBuffer[len - 2] == padding)
}

缓冲区的长度为1,如果为-2,则运行时无法识别。
或者:

  • 用多余的=字符填充输入,使其长度为%4(包括空格
  • 使用流 Package 器更改输入
  • 等待错误修复

相关问题