サプライズ!これは内部バッファ オーバーフローのようです。私が見つけたものを共有しますが、まだ実際の証拠ではありません。
Stream クラスのメソッドのコードCopyTo
は次のとおりです: (リフレクターで取得)
public void CopyTo(Stream destination, int bufferSize)
{
//bunch of non relevant validations...
this.InternalCopyTo(destination, bufferSize);
}
コードInternalCopyTo
は次のとおりです。
private void InternalCopyTo(Stream destination, int bufferSize)
{
byte[] array = new byte[bufferSize];
int count;
while ((count = this.Read(array, 0, array.Length)) != 0)
{
destination.Write(array, 0, count);
}
}
コンソール ストリーム インスタンスの型は__ConsoleStream
(System.IO の封印された内部クラス) で、そのRead
メソッド コードは次のとおりです。
public override int Read([In] [Out] byte[] buffer, int offset, int count)
{
//bunch of non relevant validations...
int errorCode = 0;
int num = __ConsoleStream.ReadFileNative(this._handle, buffer, offset, count, 0, out errorCode);
if (num == -1)
{
__Error.WinIOError(errorCode, string.Empty);
}
return num;
}
最後ReadFileNative
に __ConsoleStream のコード:
private unsafe static int ReadFileNative(SafeFileHandle hFile, byte[] bytes, int offset, int count, int mustBeZero, out int errorCode)
{
if (bytes.Length - offset < count)
{
throw new IndexOutOfRangeException(Environment.GetResourceString("IndexOutOfRange_IORaceCondition"));
}
if (bytes.Length == 0)
{
errorCode = 0;
return 0;
}
__ConsoleStream.WaitForAvailableConsoleInput(hFile);
int result;
int num;
fixed (byte* ptr = bytes)
{
num = __ConsoleStream.ReadFile(hFile, ptr + (IntPtr)offset / 1, count, out result, Win32Native.NULL);
}
if (num != 0)
{
errorCode = 0;
return result;
}
errorCode = Marshal.GetLastWin32Error();
if (errorCode == 109)
{
return 0;
}
return -1;
}
ReadFile
メソッドは低レベルの呼び出しです。
[DllImport("kernel32.dll", SetLastError = true)]
private unsafe static extern int ReadFile(SafeFileHandle handle, byte* bytes, int numBytesToRead, out int numBytesRead, IntPtr mustBeZero);
この時点での私の仮定は、舞台裏で 40 バイトが内部データのどこかに「予約」されているため、バッファがそれ以下の場合、このコンソール アプリケーションの場合はプロセス名である予約データが表示されます。
もっと時間があれば、これを調査し続けて再現を試みます。このケースは非常に特殊です。両方のストリームが同じ「ファイル」を指しているため、読み取り中に書き込むことができるからです。