Я обновил среду выполнения с netcoreapp3.1 до NET 5, и код, который преобразовывал байты base64, содержащие символы LF, в строку без ошибок, начал падать с IndexOutOfRangeException. Поведение одинаково для платформ Windows и Linux.
Я уже отправил отчет об ошибке, но все равно решил спросить, есть ли что-то неправильное или подверженное ошибкам с этим кодом.
На данный момент единственным обходным решением, которое я могу придумать, является добавление потока промежуточного программного обеспечения, который удалит все символы 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
@jdweng Нет, это не так, о чем ты говоришь?
@CodeCaster Я думаю, что они искренне пытаются помочь, но поразительно, насколько плоха эта помощь.
Этот пример упрощен для демонстрации минимального воспроизведения. В реальном сервисе у меня есть base64 ввод большого количества байтов, которые читаются из потока, поэтому я не могу просто преобразовать их на месте. У меня высоконагруженный сервис, поэтому память просто умрет, если я не буду декодировать base64 в потоковом режиме.
Да, проблема в том, что я не контролирую производственную сторону, поэтому единственный вариант - изменить ввод таким образом, чтобы он не содержал разделителей LF. Или дождаться какого-нибудь патча среды выполнения или любого другого более простого обходного пути.





Криптострим вызывает:
int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, ...)
С входным буфером, смещение 0, счет 8 (были прочитаны два полных блока, 2*4).
FromBase64Transform сохраняет некоторое внутреннее состояние и возвращает 6 (записано шесть байтов вывода), а затем получает последний вызов:
byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
С ('m\0\0\0', 0, 1). Это вызывает ошибку в FromBase64Transform, особенно в агрессивно встроенном методе:
private static int GetOutputSize(int bytesToTransform, Span<byte> tmpBuffer)
{
// ...
if (tmpBuffer[len - 2] == padding)
}
Буфер имеет длину 1, начиная с -2, что не оценивается средой выполнения.
Либо:
=Первый вариант выглядит проще, чем второй. Возможно воспользуюсь, спасибо
Это не верно!!!! Вам не хватает base64Str = Convert.ToBase64String(base64Bytes)