1
0
mirror of https://github.com/medigor/example-native-api-rs.git synced 2025-06-06 23:26:13 +02:00

remove ub

This commit is contained in:
medigor 2023-01-04 19:39:33 +03:00
parent 03e499d28b
commit 3623a66f1c

View File

@ -1,7 +1,6 @@
use std::{ use std::{
ffi::{c_int, c_long, c_ulong, c_void}, ffi::{c_int, c_long, c_ulong, c_void},
mem::size_of, ptr::{self, NonNull},
ptr,
slice::{from_raw_parts, from_raw_parts_mut}, slice::{from_raw_parts, from_raw_parts_mut},
}; };
@ -64,55 +63,59 @@ impl<'a> ReturnValue<'a> {
} }
pub fn set_str(self, val: &[u16]) { pub fn set_str(self, val: &[u16]) {
let Some(data) = self.mem.alloc_memory::<u16>(val.len()) else { let Some(ptr) = self.mem.alloc_str(val.len()) else {
*self.result = false; *self.result = false;
return; return;
}; };
data.copy_from_slice(val); unsafe { ptr::copy_nonoverlapping(val.as_ptr(), ptr.as_ptr(), val.len()) };
self.variant.vt = VariantType::PWSTR; self.variant.vt = VariantType::PWSTR;
self.variant.value.data_str.ptr = data.as_ptr() as *mut u16; self.variant.value.data_str.ptr = ptr.as_ptr();
self.variant.value.data_str.len = data.len() as u32; self.variant.value.data_str.len = val.len() as u32;
} }
pub fn set_blob(self, val: &[u8]) { pub fn set_blob(self, val: &[u8]) {
let Some(data) = self.mem.alloc_memory::<u8>(val.len()) else { let Some(ptr) = self.mem.alloc_blob(val.len()) else {
*self.result = false; *self.result = false;
return; return;
}; };
data.copy_from_slice(val); unsafe { ptr::copy_nonoverlapping(val.as_ptr(), ptr.as_ptr(), val.len()) };
self.variant.vt = VariantType::BLOB; self.variant.vt = VariantType::BLOB;
self.variant.value.data_blob.ptr = data.as_ptr() as *mut u8; self.variant.value.data_blob.ptr = ptr.as_ptr();
self.variant.value.data_blob.len = data.len() as u32; self.variant.value.data_blob.len = val.len() as u32;
} }
pub fn alloc_str(self, len: usize) -> Option<&'a mut [u16]> { pub fn alloc_str(self, len: usize) -> Option<&'a mut [u16]> {
let Some(data) = self.mem.alloc_memory::<u16>(len) else { let Some(ptr) = self.mem.alloc_str(len) else {
*self.result = false; *self.result = false;
return None; return None;
}; };
self.variant.vt = VariantType::PWSTR; unsafe { ptr::write_bytes(ptr.as_ptr(), 0, len) };
self.variant.value.data_str.ptr = data.as_ptr() as *mut u16;
self.variant.value.data_str.len = data.len() as u32;
Some(data) self.variant.vt = VariantType::PWSTR;
self.variant.value.data_str.ptr = ptr.as_ptr();
self.variant.value.data_str.len = len as u32;
Some(unsafe { from_raw_parts_mut(ptr.as_ptr(), len) })
} }
pub fn alloc_blob(self, len: usize) -> Option<&'a mut [u8]> { pub fn alloc_blob(self, len: usize) -> Option<&'a mut [u8]> {
let Some(data) = self.mem.alloc_memory::<u8>(len) else { let Some(ptr) = self.mem.alloc_blob(len) else {
*self.result = false; *self.result = false;
return None; return None;
}; };
self.variant.vt = VariantType::BLOB; unsafe { ptr::write_bytes(ptr.as_ptr(), 0, len) };
self.variant.value.data_blob.ptr = data.as_ptr() as *mut u8;
self.variant.value.data_blob.len = data.len() as u32;
Some(data) self.variant.vt = VariantType::BLOB;
self.variant.value.data_blob.ptr = ptr.as_ptr();
self.variant.value.data_blob.len = len as u32;
Some(unsafe { from_raw_parts_mut(ptr.as_ptr(), len) })
} }
} }
@ -338,11 +341,11 @@ unsafe extern "system" fn register_extension_as<T: Addin>(
let extension_name = component.addin.register_extension_as(); let extension_name = component.addin.register_extension_as();
let Some(data) = allocator.alloc_memory::<u16>(extension_name.len()) else { let Some(ptr) = allocator.alloc_str(extension_name.len()) else {
return false; return false;
}; };
data.copy_from_slice(extension_name); ptr::copy_nonoverlapping(extension_name.as_ptr(), ptr.as_ptr(), extension_name.len());
*name = data.as_mut_ptr(); *name = ptr.as_ptr();
true true
} }
@ -373,12 +376,12 @@ unsafe extern "system" fn get_prop_name<T: Addin>(
let Some(prop_name) = component.addin.get_prop_name(num as usize, alias as usize) else { let Some(prop_name) = component.addin.get_prop_name(num as usize, alias as usize) else {
return ptr::null(); return ptr::null();
}; };
let Some(name) = allocator.alloc_memory::<u16>(prop_name.len()) else { let Some(ptr) = allocator.alloc_str(prop_name.len()) else {
return ptr::null(); return ptr::null();
}; };
ptr::copy_nonoverlapping(prop_name.as_ptr(), ptr.as_ptr(), prop_name.len());
name.copy_from_slice(prop_name); ptr.as_ptr()
name.as_ptr()
} }
unsafe extern "system" fn get_prop_val<T: Addin>( unsafe extern "system" fn get_prop_val<T: Addin>(
@ -446,12 +449,13 @@ unsafe extern "system" fn get_method_name<T: Addin>(
let Some(method_name) = component.addin.get_method_name(num as usize, alias as usize) else { let Some(method_name) = component.addin.get_method_name(num as usize, alias as usize) else {
return ptr::null(); return ptr::null();
}; };
let Some(name) = allocator.alloc_memory::<u16>(method_name.len()) else { let Some(ptr) = allocator.alloc_str(method_name.len()) else {
return ptr::null(); return ptr::null();
}; };
name.copy_from_slice(method_name); ptr::copy_nonoverlapping(method_name.as_ptr(), ptr.as_ptr(), method_name.len());
name.as_ptr()
ptr.as_ptr()
} }
unsafe extern "system" fn get_n_params<T: Addin>(this: &mut This<1, T>, num: c_long) -> c_long { unsafe extern "system" fn get_n_params<T: Addin>(this: &mut This<1, T>, num: c_long) -> c_long {
@ -672,16 +676,26 @@ struct MemoryManagerVTable {
#[repr(C)] #[repr(C)]
struct MemoryManager { struct MemoryManager {
vptr1: &'static MemoryManagerVTable, vptr: &'static MemoryManagerVTable,
} }
impl MemoryManager { impl MemoryManager {
pub fn alloc_memory<'a, T>(&self, size: usize) -> Option<&'a mut [T]> { pub fn alloc_blob(&self, size: usize) -> Option<NonNull<u8>> {
let mut data = ptr::null_mut::<c_void>(); let mut ptr = ptr::null_mut::<c_void>();
unsafe { unsafe {
if (self.vptr1.alloc_memory)(self, &mut data, (size * size_of::<T>()) as c_ulong) { if (self.vptr.alloc_memory)(self, &mut ptr, size as c_ulong) {
let d = from_raw_parts_mut(data as *mut T, size); NonNull::new(ptr as *mut u8)
Some(d) } else {
None
}
}
}
pub fn alloc_str(&self, size: usize) -> Option<NonNull<u16>> {
let mut ptr = ptr::null_mut::<c_void>();
unsafe {
if (self.vptr.alloc_memory)(self, &mut ptr, size as c_ulong * 2) {
NonNull::new(ptr as *mut u16)
} else { } else {
None None
} }