Skip to content

Commit

Permalink
Consistent allocation failure for windows-registry (#3215)
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr authored Aug 22, 2024
1 parent 35663fa commit 89d94b5
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 74 deletions.
1 change: 0 additions & 1 deletion crates/libs/registry/src/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ windows_targets::link!("kernel32.dll" "system" fn HeapFree(hheap : HANDLE, dwfla
pub type BOOL = i32;
pub const ERROR_INVALID_DATA: WIN32_ERROR = 13u32;
pub const ERROR_NO_MORE_ITEMS: WIN32_ERROR = 259u32;
pub const ERROR_OUTOFMEMORY: WIN32_ERROR = 14u32;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct FILETIME {
Expand Down
31 changes: 15 additions & 16 deletions crates/libs/registry/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ pub struct Data {

impl Data {
// Creates a buffer with the specified length of zero bytes.
pub fn new(len: usize) -> Result<Self> {
pub fn new(len: usize) -> Self {
unsafe {
let bytes = Self::alloc(len)?;
let bytes = Self::alloc(len);

if len > 0 {
core::ptr::write_bytes(bytes.ptr, 0, len);
}

Ok(bytes)
bytes
}
}

Expand All @@ -30,34 +30,34 @@ impl Data {
}

// Creates a buffer by copying the bytes from the slice.
pub fn from_slice(slice: &[u8]) -> Result<Self> {
pub fn from_slice(slice: &[u8]) -> Self {
unsafe {
let bytes = Self::alloc(slice.len())?;
let bytes = Self::alloc(slice.len());

if !slice.is_empty() {
core::ptr::copy_nonoverlapping(slice.as_ptr(), bytes.ptr, slice.len());
}

Ok(bytes)
bytes
}
}

// Allocates an uninitialized buffer.
unsafe fn alloc(len: usize) -> Result<Self> {
unsafe fn alloc(len: usize) -> Self {
if len == 0 {
Ok(Self {
Self {
ptr: null_mut(),
len: 0,
})
}
} else {
// This pointer will have at least 8 byte alignment.
let ptr = HeapAlloc(GetProcessHeap(), 0, len) as *mut u8;

if ptr.is_null() {
Err(Error::from_hresult(HRESULT::from_win32(ERROR_OUTOFMEMORY)))
} else {
Ok(Self { ptr, len })
panic!("allocation failed");
}

Self { ptr, len }
}
}
}
Expand Down Expand Up @@ -96,7 +96,7 @@ impl core::ops::DerefMut for Data {

impl Clone for Data {
fn clone(&self) -> Self {
Self::from_slice(self).unwrap()
Self::from_slice(self)
}
}

Expand All @@ -114,9 +114,8 @@ impl core::fmt::Debug for Data {
}
}

impl<const N: usize> TryFrom<[u8; N]> for Data {
type Error = Error;
fn try_from(from: [u8; N]) -> Result<Self> {
impl<const N: usize> From<[u8; N]> for Data {
fn from(from: [u8; N]) -> Self {
Self::from_slice(&from)
}
}
2 changes: 1 addition & 1 deletion crates/libs/registry/src/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ impl Key {
pub fn get_value<T: AsRef<str>>(&self, name: T) -> Result<Value> {
let name = pcwstr(name);
let (ty, len) = unsafe { self.raw_get_info(name.as_raw())? };
let mut data = Data::new(len)?;
let mut data = Data::new(len);
unsafe { self.raw_get_bytes(name.as_raw(), &mut data)? };
Ok(Value { data, ty })
}
Expand Down
66 changes: 30 additions & 36 deletions crates/libs/registry/src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,12 @@ impl AsRef<[u8]> for Value {
}
}

impl TryFrom<u32> for Value {
type Error = Error;
fn try_from(from: u32) -> Result<Self> {
Ok(Self {
data: from.to_le_bytes().try_into()?,
impl From<u32> for Value {
fn from(from: u32) -> Self {
Self {
data: from.to_le_bytes().into(),
ty: Type::U32,
})
}
}
}

Expand All @@ -55,13 +54,12 @@ impl TryFrom<Value> for u32 {
}
}

impl TryFrom<u64> for Value {
type Error = Error;
fn try_from(from: u64) -> Result<Self> {
Ok(Self {
data: from.to_le_bytes().try_into()?,
impl From<u64> for Value {
fn from(from: u64) -> Self {
Self {
data: from.to_le_bytes().into(),
ty: Type::U64,
})
}
}
}

Expand All @@ -82,13 +80,12 @@ impl TryFrom<Value> for String {
}
}

impl TryFrom<&str> for Value {
type Error = Error;
fn try_from(from: &str) -> Result<Self> {
Ok(Self {
data: Data::from_slice(pcwstr(from).as_bytes())?,
impl From<&str> for Value {
fn from(from: &str) -> Self {
Self {
data: Data::from_slice(pcwstr(from).as_bytes()),
ty: Type::String,
})
}
}
}

Expand Down Expand Up @@ -117,33 +114,30 @@ impl TryFrom<Value> for HSTRING {
}
}

impl TryFrom<&HSTRING> for Value {
type Error = Error;
fn try_from(from: &HSTRING) -> Result<Self> {
Ok(Self {
data: Data::from_slice(as_bytes(from))?,
impl From<&HSTRING> for Value {
fn from(from: &HSTRING) -> Self {
Self {
data: Data::from_slice(as_bytes(from)),
ty: Type::String,
})
}
}
}

impl TryFrom<&[u8]> for Value {
type Error = Error;
fn try_from(from: &[u8]) -> Result<Self> {
Ok(Self {
data: Data::from_slice(from)?,
impl From<&[u8]> for Value {
fn from(from: &[u8]) -> Self {
Self {
data: Data::from_slice(from),
ty: Type::Bytes,
})
}
}
}

impl<const N: usize> TryFrom<[u8; N]> for Value {
type Error = Error;
fn try_from(from: [u8; N]) -> Result<Self> {
Ok(Self {
data: Data::from_slice(&from)?,
impl<const N: usize> From<[u8; N]> for Value {
fn from(from: [u8; N]) -> Self {
Self {
data: Data::from_slice(&from),
ty: Type::Bytes,
})
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions crates/libs/registry/src/value_iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl<'a> ValueIterator<'a> {
key,
range: 0..count as usize,
name: vec![0; name_max_len as usize + 1],
data: Data::new(value_max_len as usize)?,
data: Data::new(value_max_len as usize),
})
}
}
Expand Down Expand Up @@ -72,7 +72,7 @@ impl<'a> Iterator for ValueIterator<'a> {
Some((
name,
Value {
data: Data::from_slice(&self.data[0..data_len as usize]).unwrap(),
data: Data::from_slice(&self.data[0..data_len as usize]),
ty: ty.into(),
},
))
Expand Down
28 changes: 14 additions & 14 deletions crates/tests/registry/tests/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,27 @@ fn value() -> Result<()> {
_ = CURRENT_USER.remove_tree(test_key);
let key = CURRENT_USER.create(test_key)?;

key.set_value("u32", &Value::try_from(123u32)?)?;
key.set_value("u32", &Value::from(123u32))?;
assert_eq!(key.get_type("u32")?, Type::U32);
assert_eq!(key.get_value("u32")?, Value::try_from(123u32)?);
assert_eq!(key.get_value("u32")?, Value::from(123u32));
assert_eq!(key.get_u32("u32")?, 123u32);
assert_eq!(key.get_u64("u32")?, 123u64);
assert_eq!(u32::try_from(key.get_value("u32")?)?, 123u32);

assert_eq!(unsafe { key.raw_get_info(w!("u32"))? }, (Type::U32, 4));

key.set_value("u64", &Value::try_from(123u64)?)?;
key.set_value("u64", &Value::from(123u64))?;
assert_eq!(key.get_type("u64")?, Type::U64);
assert_eq!(key.get_value("u64")?, Value::try_from(123u64)?);
assert_eq!(key.get_value("u64")?, Value::from(123u64));
assert_eq!(key.get_u32("u64")?, 123u32);
assert_eq!(key.get_u64("u64")?, 123u64);
assert_eq!(u64::try_from(key.get_value("u64")?)?, 123u64);

assert_eq!(unsafe { key.raw_get_info(w!("u64"))? }, (Type::U64, 8));

key.set_value("string", &Value::try_from("string")?)?;
key.set_value("string", &Value::from("string"))?;
assert_eq!(key.get_type("string")?, Type::String);
assert_eq!(key.get_value("string")?, Value::try_from("string")?);
assert_eq!(key.get_value("string")?, Value::from("string"));
assert_eq!(key.get_string("string")?, "string");
assert_eq!(String::try_from(key.get_value("string")?)?, "string");

Expand All @@ -36,7 +36,7 @@ fn value() -> Result<()> {
(Type::String, 14)
);

let mut value = Value::try_from("expand")?;
let mut value = Value::from("expand");
value.set_ty(Type::ExpandString);
assert_eq!(value.ty(), Type::ExpandString);
key.set_value("expand", &value)?;
Expand All @@ -49,13 +49,13 @@ fn value() -> Result<()> {
(Type::ExpandString, 14)
);

key.set_value("bytes", &Value::try_from([1u8, 2u8, 3u8])?)?;
key.set_value("bytes", &Value::from([1u8, 2u8, 3u8]))?;
assert_eq!(key.get_type("bytes")?, Type::Bytes);
assert_eq!(key.get_value("bytes")?, Value::try_from([1, 2, 3])?);
assert_eq!(key.get_value("bytes")?, Value::from([1, 2, 3]));

assert_eq!(unsafe { key.raw_get_info(w!("bytes"))? }, (Type::Bytes, 3));

let mut value = Value::try_from([1u8, 2u8, 3u8, 4u8].as_slice())?;
let mut value = Value::from([1u8, 2u8, 3u8, 4u8].as_slice());
value.set_ty(Type::Other(1234));
key.set_value("slice", &value)?;
assert_eq!(key.get_type("slice")?, Type::Other(1234));
Expand All @@ -66,9 +66,9 @@ fn value() -> Result<()> {
(Type::Other(1234), 4)
);

key.set_value("hstring", &Value::try_from(h!("HSTRING"))?)?;
key.set_value("hstring", &Value::from(h!("HSTRING")))?;
assert_eq!(key.get_type("hstring")?, Type::String);
assert_eq!(key.get_value("hstring")?, Value::try_from(h!("HSTRING"))?);
assert_eq!(key.get_value("hstring")?, Value::from(h!("HSTRING")));
assert_eq!(key.get_string("hstring")?, "HSTRING");
assert_eq!(HSTRING::try_from(key.get_value("hstring")?)?, "HSTRING");

Expand All @@ -77,9 +77,9 @@ fn value() -> Result<()> {
(Type::String, 16)
);

let abc = Value::try_from("abc")?;
let abc = Value::from("abc");
assert_eq!(abc.as_wide(), &[97, 98, 99, 0]);
let abc = Value::try_from(h!("abcd"))?;
let abc = Value::from(h!("abcd"));
assert_eq!(abc.as_wide(), &[97, 98, 99, 100, 0]);

Ok(())
Expand Down
6 changes: 3 additions & 3 deletions crates/tests/registry/tests/values.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ fn values() -> Result<()> {
assert_eq!(
names,
[
("u32".to_string(), Value::try_from(123u32)?),
("u64".to_string(), Value::try_from(456u64)?),
("string".to_string(), Value::try_from("hello world")?),
("u32".to_string(), Value::from(123u32)),
("u64".to_string(), Value::from(456u64)),
("string".to_string(), Value::from("hello world")),
]
);

Expand Down
1 change: 0 additions & 1 deletion crates/tools/bindings/src/registry.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
--filter
Windows.Win32.Foundation.ERROR_INVALID_DATA
Windows.Win32.Foundation.ERROR_NO_MORE_ITEMS
Windows.Win32.Foundation.ERROR_OUTOFMEMORY
Windows.Win32.System.Memory.GetProcessHeap
Windows.Win32.System.Memory.HeapAlloc
Windows.Win32.System.Memory.HeapFree
Expand Down

0 comments on commit 89d94b5

Please sign in to comment.