Skip to content

Commit f6c49f4

Browse files
authored
Ensure that HSTRING builder provides initialized memory (#3141)
1 parent 12a60df commit f6c49f4

File tree

3 files changed

+23
-17
lines changed

3 files changed

+23
-17
lines changed

crates/libs/strings/src/hstring_builder.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@ pub struct HStringBuilder(*mut HStringHeader);
99
impl HStringBuilder {
1010
/// Creates a preallocated `HSTRING` value.
1111
pub fn new(len: usize) -> Result<Self> {
12-
Ok(Self(HStringHeader::alloc(len.try_into()?)?))
12+
let header = HStringHeader::alloc(len.try_into()?)?;
13+
14+
if len > 0 {
15+
unsafe { core::ptr::write_bytes((*header).data, 0, len) };
16+
}
17+
18+
Ok(Self(header))
1319
}
1420

1521
/// Shortens the string by removing any trailing 0 characters.

crates/libs/strings/src/hstring_header.rs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,26 @@ pub struct HStringHeader {
1414
}
1515

1616
impl HStringHeader {
17-
pub fn alloc(len: u32) -> Result<*mut HStringHeader> {
17+
pub fn alloc(len: u32) -> Result<*mut Self> {
1818
if len == 0 {
1919
return Ok(core::ptr::null_mut());
2020
}
2121

2222
// Allocate enough space for header and two bytes per character.
2323
// The space for the terminating null character is already accounted for inside of `HStringHeader`.
24-
let bytes = core::mem::size_of::<HStringHeader>() + 2 * len as usize;
24+
let bytes = core::mem::size_of::<Self>() + 2 * len as usize;
2525

2626
#[cfg(windows)]
27-
let header = unsafe { bindings::HeapAlloc(bindings::GetProcessHeap(), 0, bytes) }
28-
as *mut HStringHeader;
27+
let header =
28+
unsafe { bindings::HeapAlloc(bindings::GetProcessHeap(), 0, bytes) } as *mut Self;
2929

3030
#[cfg(not(windows))]
3131
let header = unsafe {
3232
extern "C" {
3333
fn malloc(bytes: usize) -> *mut core::ffi::c_void;
3434
}
3535

36-
malloc(bytes) as *mut HStringHeader
36+
malloc(bytes) as *mut Self
3737
};
3838

3939
if header.is_null() {
@@ -42,7 +42,7 @@ impl HStringHeader {
4242

4343
unsafe {
4444
// Use `ptr::write` (since `header` is unintialized). `HStringHeader` is safe to be all zeros.
45-
header.write(core::mem::MaybeUninit::<HStringHeader>::zeroed().assume_init());
45+
header.write(core::mem::MaybeUninit::<Self>::zeroed().assume_init());
4646
(*header).len = len;
4747
(*header).count = RefCount::new(1);
4848
(*header).data = &mut (*header).buffer_start;
@@ -51,36 +51,32 @@ impl HStringHeader {
5151
Ok(header)
5252
}
5353

54-
pub unsafe fn free(header: *mut HStringHeader) {
54+
pub unsafe fn free(header: *mut Self) {
5555
if header.is_null() {
5656
return;
5757
}
5858

59-
let header = header as *mut _;
60-
6159
#[cfg(windows)]
62-
{
63-
bindings::HeapFree(bindings::GetProcessHeap(), 0, header);
64-
}
60+
bindings::HeapFree(bindings::GetProcessHeap(), 0, header as *mut _);
6561

6662
#[cfg(not(windows))]
6763
{
6864
extern "C" {
6965
fn free(ptr: *mut core::ffi::c_void);
7066
}
7167

72-
free(header);
68+
free(header as *mut _);
7369
}
7470
}
7571

76-
pub fn duplicate(&self) -> Result<*mut HStringHeader> {
72+
pub fn duplicate(&self) -> Result<*mut Self> {
7773
if self.flags & HSTRING_REFERENCE_FLAG == 0 {
7874
// If this is not a "fast pass" string then simply increment the reference count.
7975
self.count.add_ref();
80-
Ok(self as *const HStringHeader as *mut HStringHeader)
76+
Ok(self as *const Self as *mut Self)
8177
} else {
8278
// Otherwise, allocate a new string and copy the value into the new string.
83-
let copy = HStringHeader::alloc(self.len)?;
79+
let copy = Self::alloc(self.len)?;
8480
// SAFETY: since we are duplicating the string it is safe to copy all data from self to the initialized `copy`.
8581
// We copy `len + 1` characters since `len` does not account for the terminating null character.
8682
unsafe {

crates/tests/strings/tests/hstring.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,9 @@ fn hstring_builder() -> Result<()> {
4747
assert_eq!(h.len(), 5);
4848
assert_eq!(h.as_wide(), HELLO);
4949

50+
// HStringBuilder will initialize memory to zero.
51+
let b = HStringBuilder::new(5)?;
52+
assert_eq!(*b, [0, 0, 0, 0, 0]);
53+
5054
Ok(())
5155
}

0 commit comments

Comments
 (0)