File tree Expand file tree Collapse file tree 2 files changed +34
-0
lines changed
Components/test/Rendering Expand file tree Collapse file tree 2 files changed +34
-0
lines changed Original file line number Diff line number Diff line change 1
1
// Copyright (c) .NET Foundation. All rights reserved.
2
2
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3
3
4
+ using System ;
4
5
using System . Buffers ;
5
6
using System . Linq ;
6
7
using Xunit ;
@@ -261,6 +262,7 @@ public void Dispose_NonEmptyBufferIsReturned()
261
262
Assert . Single ( ArrayPool . ReturnedBuffers ) ;
262
263
var returnedBuffer = Assert . Single ( ArrayPool . ReturnedBuffers ) ;
263
264
Assert . Same ( buffer , returnedBuffer ) ;
265
+ Assert . NotSame ( builder . Buffer , buffer ) ; // Prevents use after free
264
266
}
265
267
266
268
[ Fact ]
@@ -281,6 +283,21 @@ public void DoubleDispose_DoesNotReturnBufferTwice()
281
283
Assert . Same ( buffer , returnedBuffer ) ;
282
284
}
283
285
286
+ [ Fact ]
287
+ public void Dispose_ThrowsOnReuse ( )
288
+ {
289
+ // Arrange
290
+ var builder = CreateArrayBuilder ( ) ;
291
+ builder . Append ( 1 ) ;
292
+ var buffer = builder . Buffer ;
293
+
294
+ builder . Dispose ( ) ;
295
+ Assert . Single ( ArrayPool . ReturnedBuffers ) ;
296
+
297
+ // Act & Assert
298
+ Assert . Throws < ObjectDisposedException > ( ( ) => builder . Append ( 1 ) ) ;
299
+ }
300
+
284
301
[ Fact ]
285
302
public void UnusedBufferIsReturned_OnResize ( )
286
303
{
Original file line number Diff line number Diff line change @@ -160,6 +160,16 @@ public void Clear()
160
160
161
161
private void GrowBuffer ( int desiredCapacity )
162
162
{
163
+ // When we dispose, we set the count back to zero and return the array.
164
+ //
165
+ // If someone tries to do something that would require non-zero storage then
166
+ // this is a use-after-free. Throwing here is an easy way to prevent that without
167
+ // introducing overhead to every method.
168
+ if ( _disposed )
169
+ {
170
+ ThrowObjectDisposedException ( ) ;
171
+ }
172
+
163
173
var newCapacity = Math . Max ( desiredCapacity , _minCapacity ) ;
164
174
Debug . Assert ( newCapacity > _items . Length ) ;
165
175
@@ -188,12 +198,19 @@ public void Dispose()
188
198
{
189
199
_disposed = true ;
190
200
ReturnBuffer ( ) ;
201
+ _items = Empty ;
202
+ _itemsInUse = 0 ;
191
203
}
192
204
}
193
205
194
206
private static void ThrowIndexOutOfBoundsException ( )
195
207
{
196
208
throw new ArgumentOutOfRangeException ( "index" ) ;
197
209
}
210
+
211
+ private static void ThrowObjectDisposedException ( )
212
+ {
213
+ throw new ObjectDisposedException ( objectName : null ) ;
214
+ }
198
215
}
199
216
}
You can’t perform that action at this time.
0 commit comments