Skip to content

Commit 2f81224

Browse files
committed
fix(csharp): fix double free in C# wrapper
1 parent 31ebbae commit 2f81224

3 files changed

Lines changed: 44 additions & 10 deletions

File tree

‎wrappers/csharp/src/DecryptionStream.cs‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ public void FlushFinalBlock()
101101
throw new NotSupportedException();
102102
}
103103

104+
_finalBlockTransformed = true;
105+
104106
if (_inputBufferOffset > 0)
105107
{
106108
byte[] outputBuffer = DecryptLastChunk();
@@ -109,8 +111,6 @@ public void FlushFinalBlock()
109111
}
110112

111113
Array.Clear(_inputBuffer, 0, _inputBuffer.Length);
112-
113-
_finalBlockTransformed = true;
114114
}
115115

116116
public override void Flush()
@@ -188,14 +188,13 @@ private byte[] DecryptLastChunk()
188188

189189
long result = Native.OnlineDecryptorLastChunk(_native_ptr, _inputBuffer, (UIntPtr)_inputBufferOffset, aad, UIntPtr.Zero, outputBuffer, (UIntPtr)outputBuffer.Length);
190190

191+
_native_ptr = UIntPtr.Zero;
192+
191193
if (result < 0)
192194
{
193195
Utils.HandleError(result);
194196
}
195197

196-
// Here, the pointer is freed, so let's set it to 0
197-
_native_ptr = UIntPtr.Zero;
198-
199198
return outputBuffer;
200199
}
201200

‎wrappers/csharp/src/EncryptionStream.cs‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ public void FlushFinalBlock()
8989
throw new NotSupportedException();
9090
}
9191

92+
_finalBlockTransformed = true;
93+
9294
if (_inputBufferOffset > 0)
9395
{
9496
byte[] outputBuffer = EncryptLastChunk();
@@ -97,8 +99,6 @@ public void FlushFinalBlock()
9799
}
98100

99101
Array.Clear(_inputBuffer, 0, _inputBuffer.Length);
100-
101-
_finalBlockTransformed = true;
102102
}
103103

104104
public override void Flush()
@@ -175,14 +175,13 @@ private byte[] EncryptLastChunk()
175175

176176
long result = Native.OnlineEncryptorLastChunk(_native_ptr, _inputBuffer, (UIntPtr)_inputBufferOffset, aad, UIntPtr.Zero, outputBuffer, (UIntPtr)outputBuffer.Length);
177177

178+
_native_ptr = UIntPtr.Zero;
179+
178180
if (result < 0)
179181
{
180182
Utils.HandleError(result);
181183
}
182184

183-
// Here, the pointer is freed, so let's set it to 0
184-
_native_ptr = UIntPtr.Zero;
185-
186185
return outputBuffer;
187186
}
188187

‎wrappers/csharp/tests/unit-tests/TestStreams.cs‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,41 @@ public void DecryptStream()
5656
Assert.IsTrue(result.Length == 1689);
5757
Assert.IsTrue(Utils.EncodeToBase64String(result) == TestData.Base64TestDataStream);
5858
}
59+
60+
[TestMethod]
61+
public void DecryptStreamTruncatedCiphertext()
62+
{
63+
const int ChunkLength = 8;
64+
const int EncryptedChunkLength = ChunkLength + 16;
65+
66+
byte[] plaintext = new byte[3 * ChunkLength];
67+
byte[] header;
68+
byte[] ciphertext;
69+
70+
using (MemoryStream encrypted = new MemoryStream())
71+
{
72+
using (EncryptionStream ec =
73+
new EncryptionStream(TestData.BytesTestKey, [], ChunkLength, false, 0, encrypted, true))
74+
{
75+
header = ec.GetHeader();
76+
77+
ec.Write(plaintext, 0, plaintext.Length);
78+
ec.FlushFinalBlock();
79+
}
80+
81+
ciphertext = encrypted.ToArray();
82+
}
83+
84+
using MemoryStream ms = new MemoryStream();
85+
86+
Assert.ThrowsException<DevolutionsCryptoException>(() =>
87+
{
88+
using DecryptionStream dc =
89+
new DecryptionStream(TestData.BytesTestKey, [], header, false, ms, true);
90+
91+
dc.Write(ciphertext, 0, ciphertext.Length - EncryptedChunkLength);
92+
dc.FlushFinalBlock();
93+
});
94+
}
5995
}
6096
}

0 commit comments

Comments
 (0)