Buffer sizes
authorGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Fri, 8 Oct 2010 01:15:55 +0000 (21:15 -0400)
committerGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Fri, 8 Oct 2010 19:31:43 +0000 (15:31 -0400)
workingBlock should be the InputBlockSize and currentBlock the
OutputBlockSize. Allocate currentBlock lazily.

Test contributed by Bassam Tabbara.
Fixes bug #644740.

mcs/class/corlib/System.Security.Cryptography/CryptoStream.cs
mcs/class/corlib/Test/System.Security.Cryptography/CryptoStreamTest.cs

index 3c4890d610590c55ce5a801aee695e5135361b83..48f3794f8cb04684e4d656580b8ac9fd33e2f415 100644 (file)
@@ -71,14 +71,7 @@ namespace System.Security.Cryptography {
                        _mode = mode;
                        _disposed = false;
                        if (transform != null) {
-                               if (mode == CryptoStreamMode.Read) {
-                                       _currentBlock = new byte [transform.InputBlockSize];
-                                       _workingBlock = new byte [transform.InputBlockSize];
-                               }
-                               else if (mode == CryptoStreamMode.Write) {
-                                       _currentBlock = new byte [transform.OutputBlockSize];
-                                       _workingBlock = new byte [transform.OutputBlockSize];
-                               }
+                               _workingBlock = new byte [transform.InputBlockSize];
                        }
                }
 
@@ -250,7 +243,7 @@ namespace System.Security.Cryptography {
                        }
 
                        if (_stream == null)
-                               throw new ArgumentNullException ("inner stream was diposed");
+                               throw new ArgumentNullException ("inner stream was disposed");
 
                        int buffer_length = count;
 
@@ -267,6 +260,9 @@ namespace System.Security.Cryptography {
                        int bufferPos = offset;
                        while (count > 0) {
                                if (_partialCount == _transform.InputBlockSize) {
+                                       if (_currentBlock == null)
+                                               _currentBlock = new byte [_transform.OutputBlockSize];
+
                                        // use partial block to avoid (re)allocation
                                        int len = _transform.TransformBlock (_workingBlock, 0, _partialCount, _currentBlock, 0);
                                        _stream.Write (_currentBlock, 0, len);
index 8d306d3e6e2c09f76aa7adfe9a49231bf5238b75..580fac8e10750c2f4695a3949877b601f1337861 100644 (file)
@@ -1457,6 +1457,16 @@ namespace MonoTests.System.Security.Cryptography {
                        CryptoStream cs = new CryptoStream (Stream.Null, SHA1.Create (), (CryptoStreamMode) 0xff);
                }
 
+               [Test]
+               public void OutputBlock_Smaller ()
+               {
+                       // The OutputBlockSize is smaller than the InputBlockSize
+                       using (CryptoStream cs = new CryptoStream(Stream.Null, new MyCryptAlgorithm(), CryptoStreamMode.Write)) {
+                               byte[] buffer = new byte[512 * 1024];
+                               cs.Write(buffer, 0, buffer.Length);
+                       }
+               }
+
                class MyCryptoStream : CryptoStream {
                        public bool DisposeCalled { get; private set;}
 
@@ -1629,6 +1639,25 @@ namespace MonoTests.System.Security.Cryptography {
                        }
                }
 
+               class MyCryptAlgorithm : ICryptoTransform {
+                       public bool CanReuseTransform { get { return true; } }
+                       public bool CanTransformMultipleBlocks { get { return false; } }
+                       public int InputBlockSize { get { return 128 * 1024; } }
+                       public int OutputBlockSize { get { return 64 * 1024; } }
+
+                       public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+                       {
+                               return this.OutputBlockSize;
+                       }
+
+                       public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
+                       {
+                               return new byte[this.OutputBlockSize];
+                       }
+
+                       public void Dispose() {}
+               }
+
                class MyStream : Stream {
                        public bool FlushCounterEnabled;
                        public int FlushCounter;