@@ -32,13 +32,18 @@ public static unsafe partial class NativeMemory
32
32
// The C standard and POSIX requires size to be a multiple of alignment and we want an "empty" allocation for zero
33
33
// POSIX additionally requires alignment to be at least sizeof(void*)
34
34
35
- // The adjustment for byteCount can overflow here, but such overflow is "harmless". This is because of the requirement
36
- // that alignment be a power of two and that byteCount be a multiple of alignment. Given both of these constraints
37
- // we should only overflow for byteCount > (nuint.MaxValue & ~(alignment - 1)). When such an overflow occurs we will
38
- // get a result that is less than alignment which will cause the allocation to fail.
35
+ // The adjustment for byteCount can overflow here, and such overflow is generally "harmless". This is because of the
36
+ // requirement that alignment be a power of two and that byteCount be a multiple of alignment. Given both of these
37
+ // constraints we should only overflow for byteCount > (nuint.MaxValue & ~(alignment - 1)). When such an overflow
38
+ // occurs we will get a result that is less than alignment which will cause the allocation to fail.
39
+ //
40
+ // However, posix_memalign differs from aligned_alloc in that it may return a valid pointer for zero and we need to
41
+ // ensure we OOM for this scenario (which can occur for `nuint.MaxValue`) and so we have to check the adjusted size.
39
42
40
43
nuint adjustedAlignment = Math . Max ( alignment , ( uint ) sizeof ( void * ) ) ;
41
- void * result = Interop . Sys . AlignedAlloc ( adjustedAlignment , ( byteCount != 0 ) ? ( byteCount + ( adjustedAlignment - 1 ) ) & ~ ( adjustedAlignment - 1 ) : adjustedAlignment ) ;
44
+ nuint adjustedByteCount = ( byteCount != 0 ) ? ( byteCount + ( adjustedAlignment - 1 ) ) & ~ ( adjustedAlignment - 1 ) : adjustedAlignment ;
45
+
46
+ void * result = ( adjustedByteCount < byteCount ) ? null : Interop . Sys . AlignedAlloc ( adjustedAlignment , adjustedByteCount ) ;
42
47
43
48
if ( result == null )
44
49
{
@@ -88,13 +93,18 @@ public static void AlignedFree(void* ptr)
88
93
// The C standard and POSIX requires size to be a multiple of alignment and we want an "empty" allocation for zero
89
94
// POSIX additionally requires alignment to be at least sizeof(void*)
90
95
91
- // The adjustment for byteCount can overflow here, but such overflow is "harmless". This is because of the requirement
92
- // that alignment be a power of two and that byteCount be a multiple of alignment. Given both of these constraints
93
- // we should only overflow for byteCount > (nuint.MaxValue & ~(alignment - 1)). When such an overflow occurs we will
94
- // get a result that is less than alignment which will cause the allocation to fail.
96
+ // The adjustment for byteCount can overflow here, and such overflow is generally "harmless". This is because of the
97
+ // requirement that alignment be a power of two and that byteCount be a multiple of alignment. Given both of these
98
+ // constraints we should only overflow for byteCount > (nuint.MaxValue & ~(alignment - 1)). When such an overflow
99
+ // occurs we will get a result that is less than alignment which will cause the allocation to fail.
100
+ //
101
+ // However, posix_memalign differs from aligned_alloc in that it may return a valid pointer for zero and we need to
102
+ // ensure we OOM for this scenario (which can occur for `nuint.MaxValue`) and so we have to check the adjusted size.
95
103
96
104
nuint adjustedAlignment = Math . Max ( alignment , ( uint ) sizeof ( void * ) ) ;
97
- void * result = Interop . Sys . AlignedRealloc ( ptr , adjustedAlignment , ( byteCount != 0 ) ? ( byteCount + ( adjustedAlignment - 1 ) ) & ~ ( adjustedAlignment - 1 ) : adjustedAlignment ) ;
105
+ nuint adjustedByteCount = ( byteCount != 0 ) ? ( byteCount + ( adjustedAlignment - 1 ) ) & ~ ( adjustedAlignment - 1 ) : adjustedAlignment ;
106
+
107
+ void * result = ( adjustedByteCount < byteCount ) ? null : Interop . Sys . AlignedRealloc ( ptr , adjustedAlignment , adjustedByteCount ) ;
98
108
99
109
if ( result == null )
100
110
{
0 commit comments