Skip to content

Commit 3b92348

Browse files
committed
allocator::win32::CoTaskMem: fix ZST reallocs by always requesting at least one byte
relates to #32
1 parent 7a81257 commit 3b92348

File tree

1 file changed

+17
-5
lines changed

1 file changed

+17
-5
lines changed

src/allocator/win32/cotaskmem.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,17 @@ use core::ptr::NonNull;
1010

1111
/// [`CoTaskMemAlloc`] / [`CoTaskMemRealloc`] / [`CoTaskMemFree`]
1212
///
13+
/// Uses the default COM / "OLE task memory" allocator provided by [`CoGetMalloc`], which in turn simply uses [`Heap*`](super::Heap) functions under the hood.
14+
/// Consider using [`Heap`](super::Heap) directly instead, unless you're specifically doing COM / have documentation mandating a specific (de)allocator for interop purpouses.
15+
///
1316
/// | Rust | C |
1417
/// | ----------------------------------| ----------------------|
15-
/// | [`thin::Alloc::alloc_uninit`] | [`CoTaskMemAlloc`]
16-
/// | [`thin::Realloc::realloc_uninit`] | [`CoTaskMemRealloc`]
18+
/// | [`thin::Alloc::alloc_uninit`] | [`CoTaskMemAlloc`] <sup>\[1\]</sup>
19+
/// | [`thin::Realloc::realloc_uninit`] | [`CoTaskMemRealloc`] <sup>\[2\]</sup>
1720
/// | [`thin::Free::free`] | [`CoTaskMemFree`]
1821
///
19-
/// Uses the default COM / "OLE task memory" allocator provided by [`CoGetMalloc`], which in turn simply uses [`Heap*`](super::Heap) functions under the hood.
20-
/// Consider using [`Heap`](super::Heap) directly instead, unless you're specifically doing COM / have documentation mandating a specific (de)allocator for interop purpouses.
22+
/// 1. `size` / `layout` of 0 bytes will allocate successfully
23+
/// 2. `new_size` / `new_layout` will be rounded up to at least 1 byte, otherwise [`CoTaskMemRealloc`] would free!
2124
///
2225
/// ## References
2326
/// * [`IMalloc`](super::IMalloc) (stateful equivalent)
@@ -35,6 +38,11 @@ impl Meta for CoTaskMem {
3538
const MIN_ALIGN : Alignment = super::MEMORY_ALLOCATION_ALIGNMENT; // Verified through testing
3639
const MAX_ALIGN : Alignment = super::MEMORY_ALLOCATION_ALIGNMENT; // Verified through testing
3740
const MAX_SIZE : usize = usize::MAX;
41+
42+
/// - `CoTaskMemAlloc(0)` allocates successfully.
43+
/// - `CoTaskMemRealloc(ptr, 0)` **frees**.
44+
/// Note that [`thin::Realloc`] and [`fat::Realloc`] resolve this by always requesting at least 1 byte.
45+
///
3846
const ZST_SUPPORTED : bool = true;
3947
}
4048

@@ -90,7 +98,7 @@ unsafe impl thin::Realloc for CoTaskMem {
9098

9199
unsafe fn realloc_uninit(&self, ptr: AllocNN, new_size: usize) -> Result<AllocNN, Self::Error> {
92100
// SAFETY: ✔️ `ptr` belongs to `self` per [`thin::Realloc::realloc_uninit`]'s documented safety preconditions, and thus was allocated with CoTaskMem{Alloc,Realloc}
93-
let alloc = unsafe { CoTaskMemRealloc(ptr.as_ptr().cast(), new_size) };
101+
let alloc = unsafe { CoTaskMemRealloc(ptr.as_ptr().cast(), new_size.max(1)) };
94102
NonNull::new(alloc.cast()).ok_or(())
95103
}
96104

@@ -133,11 +141,15 @@ unsafe impl thin::Free for CoTaskMem {
133141
#[test] fn thin_nullable() { thin::test::nullable(CoTaskMem) }
134142
//#[test] fn thin_size() { ...no CoTaskMemSizeOf... }
135143
#[test] fn thin_uninit() { unsafe { thin::test::uninit_alloc_unsound(CoTaskMem) } }
144+
#[test] fn thin_uninit_realloc() { thin::test::uninit_realloc(CoTaskMem) }
136145
#[test] fn thin_zeroed() { thin::test::zeroed_alloc(CoTaskMem) }
146+
#[test] fn thin_zeroed_realloc() { thin::test::zeroed_realloc(CoTaskMem) }
137147
#[test] fn thin_zst_support() { thin::test::zst_supported_accurate(CoTaskMem) }
138148

139149
#[test] fn fat_alignment() { fat::test::alignment(CoTaskMem) }
140150
#[test] fn fat_edge_case_sizes() { fat::test::edge_case_sizes(CoTaskMem) }
141151
#[test] fn fat_uninit() { unsafe { fat::test::uninit_alloc_unsound(CoTaskMem) } }
152+
#[test] fn fat_uninit_realloc() { fat::test::uninit_realloc(CoTaskMem) }
142153
#[test] fn fat_zeroed() { fat::test::zeroed_alloc(CoTaskMem) }
154+
#[test] fn fat_zeroed_realloc() { fat::test::zeroed_realloc(CoTaskMem) }
143155
#[test] fn fat_zst_support() { fat::test::zst_supported_accurate(CoTaskMem) }

0 commit comments

Comments
 (0)