diff --git a/plugins/warp/src/matcher.rs b/plugins/warp/src/matcher.rs index 81458f8da..6352cd7ae 100644 --- a/plugins/warp/src/matcher.rs +++ b/plugins/warp/src/matcher.rs @@ -506,7 +506,7 @@ pub struct PlatformID(u64); impl From<&Platform> for PlatformID { fn from(value: &Platform) -> Self { let mut hasher = DefaultHasher::new(); - hasher.write(value.name().to_bytes()); + hasher.write(value.name().as_bytes()); Self(hasher.finish()) } } diff --git a/rust/src/architecture.rs b/rust/src/architecture.rs index 325802d9a..210ca4d33 100644 --- a/rust/src/architecture.rs +++ b/rust/src/architecture.rs @@ -27,7 +27,7 @@ use crate::{ platform::Platform, rc::*, relocation::CoreRelocationHandler, - string::BnStrCompatible, + string::AsCStr, string::*, types::{NameAndType, Type}, Endianness, @@ -1397,8 +1397,7 @@ impl CoreArchitecture { } pub fn by_name(name: &str) -> Option { - let handle = - unsafe { BNGetArchitectureByName(name.into_bytes_with_nul().as_ptr() as *mut _) }; + let handle = unsafe { BNGetArchitectureByName(name.as_cstr().as_ptr()) }; match handle.is_null() { false => Some(CoreArchitecture { handle }), true => None, @@ -1928,11 +1927,9 @@ macro_rules! cc_func { /// Contains helper methods for all types implementing 'Architecture' pub trait ArchitectureExt: Architecture { - fn register_by_name(&self, name: S) -> Option { - let name = name.into_bytes_with_nul(); - + fn register_by_name(&self, name: S) -> Option { match unsafe { - BNGetArchitectureRegisterByName(self.as_ref().handle, name.as_ref().as_ptr() as *mut _) + BNGetArchitectureRegisterByName(self.as_ref().handle, name.as_cstr().as_ptr()) } { 0xffff_ffff => None, reg => self.register_from_id(reg.into()), @@ -2008,7 +2005,7 @@ pub trait ArchitectureExt: Architecture { fn register_relocation_handler(&self, name: S, func: F) where - S: BnStrCompatible, + S: AsCStr, R: 'static + RelocationHandler> + Send @@ -2031,7 +2028,7 @@ impl ArchitectureExt for T {} pub fn register_architecture(name: S, func: F) -> &'static A where - S: BnStrCompatible, + S: AsCStr, A: 'static + Architecture> + Send + Sync + Sized, F: FnOnce(CustomArchitectureHandle, CoreArchitecture) -> A, { @@ -3114,8 +3111,6 @@ where custom_arch.skip_and_return_value(data, addr, val) } - let name = name.into_bytes_with_nul(); - let uninit_arch = ArchitectureBuilder { arch: MaybeUninit::zeroed(), func: Some(func), @@ -3205,8 +3200,7 @@ where }; unsafe { - let res = - BNRegisterArchitecture(name.as_ref().as_ptr() as *mut _, &mut custom_arch as *mut _); + let res = BNRegisterArchitecture(name.as_cstr().as_ptr(), &mut custom_arch as *mut _); assert!(!res.is_null()); diff --git a/rust/src/background_task.rs b/rust/src/background_task.rs index 0420afbfc..449e92398 100644 --- a/rust/src/background_task.rs +++ b/rust/src/background_task.rs @@ -43,9 +43,8 @@ impl BackgroundTask { Self { handle } } - pub fn new(initial_text: S, can_cancel: bool) -> Ref { - let text = initial_text.into_bytes_with_nul(); - let handle = unsafe { BNBeginBackgroundTask(text.as_ref().as_ptr() as *mut _, can_cancel) }; + pub fn new(initial_text: S, can_cancel: bool) -> Ref { + let handle = unsafe { BNBeginBackgroundTask(initial_text.as_cstr().as_ptr(), can_cancel) }; // We should always be returned a valid task. assert!(!handle.is_null()); unsafe { Ref::new(Self { handle }) } @@ -75,11 +74,8 @@ impl BackgroundTask { unsafe { BnString::from_raw(BNGetBackgroundTaskProgressText(self.handle)) } } - pub fn set_progress_text(&self, text: S) { - let progress_text = text.into_bytes_with_nul(); - unsafe { - BNSetBackgroundTaskProgressText(self.handle, progress_text.as_ref().as_ptr() as *mut _) - } + pub fn set_progress_text(&self, text: S) { + unsafe { BNSetBackgroundTaskProgressText(self.handle, text.as_cstr().as_ptr()) } } pub fn running_tasks() -> Array { diff --git a/rust/src/binary_view.rs b/rust/src/binary_view.rs index 691f42c86..c4fdab43f 100644 --- a/rust/src/binary_view.rs +++ b/rust/src/binary_view.rs @@ -263,13 +263,8 @@ pub trait BinaryViewExt: BinaryViewBase { unsafe { BNGetEndOffset(self.as_ref().handle) } } - fn add_analysis_option(&self, name: impl BnStrCompatible) { - unsafe { - BNAddAnalysisOption( - self.as_ref().handle, - name.into_bytes_with_nul().as_ref().as_ptr() as *mut _, - ) - } + fn add_analysis_option(&self, name: impl AsCStr) { + unsafe { BNAddAnalysisOption(self.as_ref().handle, name.as_cstr().as_ptr()) } } fn has_initial_analysis(&self) -> bool { @@ -393,13 +388,11 @@ pub trait BinaryViewExt: BinaryViewBase { } } - fn symbol_by_raw_name(&self, raw_name: S) -> Option> { - let raw_name = raw_name.into_bytes_with_nul(); - + fn symbol_by_raw_name(&self, raw_name: S) -> Option> { unsafe { let raw_sym_ptr = BNGetSymbolByRawName( self.as_ref().handle, - raw_name.as_ref().as_ptr() as *mut _, + raw_name.as_cstr().as_ptr(), std::ptr::null_mut(), ); match raw_sym_ptr.is_null() { @@ -418,14 +411,12 @@ pub trait BinaryViewExt: BinaryViewBase { } } - fn symbols_by_name(&self, name: S) -> Array { - let raw_name = name.into_bytes_with_nul(); - + fn symbols_by_name(&self, name: S) -> Array { unsafe { let mut count = 0; let handles = BNGetSymbolsByName( self.as_ref().handle, - raw_name.as_ref().as_ptr() as *mut _, + name.as_cstr().as_ptr(), &mut count, std::ptr::null_mut(), ); @@ -579,35 +570,32 @@ pub trait BinaryViewExt: BinaryViewBase { } } - fn define_auto_type, S: BnStrCompatible>( + fn define_auto_type, S: AsCStr>( &self, name: T, source: S, type_obj: &Type, ) -> QualifiedName { let mut raw_name = QualifiedName::into_raw(name.into()); - let source_str = source.into_bytes_with_nul(); let name_handle = unsafe { - let id_str = - BNGenerateAutoTypeId(source_str.as_ref().as_ptr() as *const _, &mut raw_name); + let id_str = BNGenerateAutoTypeId(source.as_cstr().as_ptr(), &mut raw_name); BNDefineAnalysisType(self.as_ref().handle, id_str, &mut raw_name, type_obj.handle) }; QualifiedName::free_raw(raw_name); QualifiedName::from_owned_raw(name_handle) } - fn define_auto_type_with_id, S: BnStrCompatible>( + fn define_auto_type_with_id, S: AsCStr>( &self, name: T, id: S, type_obj: &Type, ) -> QualifiedName { let mut raw_name = QualifiedName::into_raw(name.into()); - let id_str = id.into_bytes_with_nul(); let result_raw_name = unsafe { BNDefineAnalysisType( self.as_ref().handle, - id_str.as_ref().as_ptr() as *const _, + id.as_cstr().as_ptr(), &mut raw_name, type_obj.handle, ) @@ -710,11 +698,8 @@ pub trait BinaryViewExt: BinaryViewBase { } } - fn undefine_auto_type(&self, id: S) { - let id_str = id.into_bytes_with_nul(); - unsafe { - BNUndefineAnalysisType(self.as_ref().handle, id_str.as_ref().as_ptr() as *const _); - } + fn undefine_auto_type(&self, id: S) { + unsafe { BNUndefineAnalysisType(self.as_ref().handle, id.as_cstr().as_ptr()) } } fn undefine_user_type>(&self, name: T) { @@ -761,11 +746,9 @@ pub trait BinaryViewExt: BinaryViewBase { } } - fn type_by_id(&self, id: S) -> Option> { + fn type_by_id(&self, id: S) -> Option> { unsafe { - let id_str = id.into_bytes_with_nul(); - let type_handle = - BNGetAnalysisTypeById(self.as_ref().handle, id_str.as_ref().as_ptr() as *mut _); + let type_handle = BNGetAnalysisTypeById(self.as_ref().handle, id.as_cstr().as_ptr()); if type_handle.is_null() { return None; } @@ -773,11 +756,10 @@ pub trait BinaryViewExt: BinaryViewBase { } } - fn type_name_by_id(&self, id: S) -> Option { + fn type_name_by_id(&self, id: S) -> Option { unsafe { - let id_str = id.into_bytes_with_nul(); let name_handle = - BNGetAnalysisTypeNameById(self.as_ref().handle, id_str.as_ref().as_ptr() as *mut _); + BNGetAnalysisTypeNameById(self.as_ref().handle, id.as_cstr().as_ptr()); let name = QualifiedName::from_owned_raw(name_handle); // The core will return an empty qualified name if no type name was found. match name.items.is_empty() { @@ -867,31 +849,25 @@ pub trait BinaryViewExt: BinaryViewBase { unsafe { BNCancelBulkAddSegments(self.as_ref().handle) } } - fn add_section(&self, section: SectionBuilder) { + fn add_section(&self, section: SectionBuilder) { section.create(self.as_ref()); } - fn remove_auto_section(&self, name: S) { - let raw_name = name.into_bytes_with_nul(); - let raw_name_ptr = raw_name.as_ref().as_ptr() as *mut _; + fn remove_auto_section(&self, name: S) { unsafe { - BNRemoveAutoSection(self.as_ref().handle, raw_name_ptr); + BNRemoveAutoSection(self.as_ref().handle, name.as_cstr().as_ptr()); } } - fn remove_user_section(&self, name: S) { - let raw_name = name.into_bytes_with_nul(); - let raw_name_ptr = raw_name.as_ref().as_ptr() as *mut _; + fn remove_user_section(&self, name: S) { unsafe { - BNRemoveUserSection(self.as_ref().handle, raw_name_ptr); + BNRemoveUserSection(self.as_ref().handle, name.as_cstr().as_ptr()); } } - fn section_by_name(&self, name: S) -> Option> { + fn section_by_name(&self, name: S) -> Option> { unsafe { - let raw_name = name.into_bytes_with_nul(); - let name_ptr = raw_name.as_ref().as_ptr() as *mut _; - let raw_section_ptr = BNGetSectionByName(self.as_ref().handle, name_ptr); + let raw_section_ptr = BNGetSectionByName(self.as_ref().handle, name.as_cstr().as_ptr()); match raw_section_ptr.is_null() { false => Some(Section::ref_from_raw(raw_section_ptr)), true => None, @@ -1099,24 +1075,19 @@ pub trait BinaryViewExt: BinaryViewBase { unsafe { BNApplyDebugInfo(self.as_ref().handle, debug_info.handle) } } - fn show_graph_report(&self, raw_name: S, graph: &FlowGraph) { - let raw_name = raw_name.into_bytes_with_nul(); + fn show_graph_report(&self, raw_name: S, graph: &FlowGraph) { unsafe { BNShowGraphReport( self.as_ref().handle, - raw_name.as_ref().as_ptr() as *mut _, + raw_name.as_cstr().as_ptr(), graph.handle, ); } } - fn load_settings(&self, view_type_name: S) -> Result> { - let view_type_name = view_type_name.into_bytes_with_nul(); + fn load_settings(&self, view_type_name: S) -> Result> { let settings_handle = unsafe { - BNBinaryViewGetLoadSettings( - self.as_ref().handle, - view_type_name.as_ref().as_ptr() as *mut _, - ) + BNBinaryViewGetLoadSettings(self.as_ref().handle, view_type_name.as_cstr().as_ptr()) }; if settings_handle.is_null() { @@ -1126,13 +1097,11 @@ pub trait BinaryViewExt: BinaryViewBase { } } - fn set_load_settings(&self, view_type_name: S, settings: &Settings) { - let view_type_name = view_type_name.into_bytes_with_nul(); - + fn set_load_settings(&self, view_type_name: S, settings: &Settings) { unsafe { BNBinaryViewSetLoadSettings( self.as_ref().handle, - view_type_name.as_ref().as_ptr() as *mut _, + view_type_name.as_cstr().as_ptr(), settings.handle, ) }; @@ -1143,11 +1112,7 @@ pub trait BinaryViewExt: BinaryViewBase { /// # Arguments /// * `name` - the name for the tag /// * `icon` - the icon (recommended 1 emoji or 2 chars) for the tag - fn create_tag_type( - &self, - name: N, - icon: I, - ) -> Ref { + fn create_tag_type(&self, name: N, icon: I) -> Ref { let tag_type = TagType::create(self.as_ref(), name, icon); unsafe { BNAddTagType(self.as_ref().handle, tag_type.handle); @@ -1161,10 +1126,9 @@ pub trait BinaryViewExt: BinaryViewBase { } /// Get a tag type by its name. - fn tag_type_by_name(&self, name: S) -> Option> { - let name = name.into_bytes_with_nul(); + fn tag_type_by_name(&self, name: S) -> Option> { unsafe { - let handle = BNGetTagType(self.as_ref().handle, name.as_ref().as_ptr() as *mut _); + let handle = BNGetTagType(self.as_ref().handle, name.as_cstr().as_ptr()); if handle.is_null() { return None; } @@ -1175,10 +1139,9 @@ pub trait BinaryViewExt: BinaryViewBase { /// Get a tag by its id. /// /// Note this does not tell you anything about where it is used. - fn tag_by_id(&self, id: S) -> Option> { - let id = id.into_bytes_with_nul(); + fn tag_by_id(&self, id: S) -> Option> { unsafe { - let handle = BNGetTag(self.as_ref().handle, id.as_ref().as_ptr() as *mut _); + let handle = BNGetTag(self.as_ref().handle, id.as_cstr().as_ptr()); if handle.is_null() { return None; } @@ -1189,7 +1152,7 @@ pub trait BinaryViewExt: BinaryViewBase { /// Creates and adds a tag to an address /// /// User tag creations will be added to the undo buffer - fn add_tag(&self, addr: u64, t: &TagType, data: S, user: bool) { + fn add_tag(&self, addr: u64, t: &TagType, data: S, user: bool) { let tag = Tag::new(t, data); unsafe { BNAddTag(self.as_ref().handle, tag.handle, user) } @@ -1260,13 +1223,9 @@ pub trait BinaryViewExt: BinaryViewBase { result } - fn query_metadata(&self, key: S) -> Option> { - let value: *mut BNMetadata = unsafe { - BNBinaryViewQueryMetadata( - self.as_ref().handle, - key.into_bytes_with_nul().as_ref().as_ptr() as *const c_char, - ) - }; + fn query_metadata(&self, key: S) -> Option> { + let value: *mut BNMetadata = + unsafe { BNBinaryViewQueryMetadata(self.as_ref().handle, key.as_cstr().as_ptr()) }; if value.is_null() { None } else { @@ -1274,7 +1233,7 @@ pub trait BinaryViewExt: BinaryViewBase { } } - fn get_metadata(&self, key: S) -> Option> + fn get_metadata(&self, key: S) -> Option> where T: for<'a> TryFrom<&'a Metadata>, { @@ -1282,7 +1241,7 @@ pub trait BinaryViewExt: BinaryViewBase { .map(|md| T::try_from(md.as_ref()).map_err(|_| ())) } - fn store_metadata(&self, key: S, value: V, is_auto: bool) + fn store_metadata(&self, key: S, value: V, is_auto: bool) where V: Into>, { @@ -1290,20 +1249,15 @@ pub trait BinaryViewExt: BinaryViewBase { unsafe { BNBinaryViewStoreMetadata( self.as_ref().handle, - key.into_bytes_with_nul().as_ref().as_ptr() as *const c_char, + key.as_cstr().as_ptr(), md.as_ref().handle, is_auto, ) }; } - fn remove_metadata(&self, key: S) { - unsafe { - BNBinaryViewRemoveMetadata( - self.as_ref().handle, - key.into_bytes_with_nul().as_ref().as_ptr() as *const c_char, - ) - }; + fn remove_metadata(&self, key: S) { + unsafe { BNBinaryViewRemoveMetadata(self.as_ref().handle, key.as_cstr().as_ptr()) }; } /// Retrieves a list of [CodeReference]s pointing to a given address. @@ -1427,14 +1381,8 @@ pub trait BinaryViewExt: BinaryViewBase { .collect() } - fn component_by_guid(&self, guid: S) -> Option { - let name = guid.into_bytes_with_nul(); - let result = unsafe { - BNGetComponentByGuid( - self.as_ref().handle, - name.as_ref().as_ptr() as *const c_char, - ) - }; + fn component_by_guid(&self, guid: S) -> Option { + let result = unsafe { BNGetComponentByGuid(self.as_ref().handle, guid.as_cstr().as_ptr()) }; NonNull::new(result).map(|h| unsafe { Component::from_raw(h) }) } @@ -1447,14 +1395,8 @@ pub trait BinaryViewExt: BinaryViewBase { ComponentBuilder::new_from_raw(self.as_ref().handle) } - fn component_by_path(&self, path: P) -> Option { - let path = path.into_bytes_with_nul(); - let result = unsafe { - BNGetComponentByPath( - self.as_ref().handle, - path.as_ref().as_ptr() as *const c_char, - ) - }; + fn component_by_path(&self, path: P) -> Option { + let result = unsafe { BNGetComponentByPath(self.as_ref().handle, path.as_cstr().as_ptr()) }; NonNull::new(result).map(|h| unsafe { Component::from_raw(h) }) } @@ -1463,8 +1405,7 @@ pub trait BinaryViewExt: BinaryViewBase { } fn remove_component_by_guid(&self, guid: P) -> bool { - let path = guid.component_guid(); - unsafe { BNRemoveComponentByGuid(self.as_ref().handle, path.as_ptr()) } + unsafe { BNRemoveComponentByGuid(self.as_ref().handle, guid.component_guid().as_ptr()) } } fn data_variable_parent_components(&self, data_variable: &DataVariable) -> Array { @@ -1485,39 +1426,28 @@ pub trait BinaryViewExt: BinaryViewBase { unsafe { Array::new(result, count, ()) } } - fn external_library(&self, name: S) -> Option> { - let name_ptr = name.into_bytes_with_nul(); + fn external_library(&self, name: S) -> Option> { let result = unsafe { - BNBinaryViewGetExternalLibrary( - self.as_ref().handle, - name_ptr.as_ref().as_ptr() as *const c_char, - ) + BNBinaryViewGetExternalLibrary(self.as_ref().handle, name.as_cstr().as_ptr()) }; let result_ptr = NonNull::new(result)?; Some(unsafe { ExternalLibrary::ref_from_raw(result_ptr) }) } - fn remove_external_library(&self, name: S) { - let name_ptr = name.into_bytes_with_nul(); - unsafe { - BNBinaryViewRemoveExternalLibrary( - self.as_ref().handle, - name_ptr.as_ref().as_ptr() as *const c_char, - ) - }; + fn remove_external_library(&self, name: S) { + unsafe { BNBinaryViewRemoveExternalLibrary(self.as_ref().handle, name.as_cstr().as_ptr()) }; } - fn add_external_library( + fn add_external_library( &self, name: S, backing_file: Option<&ProjectFile>, auto: bool, ) -> Option> { - let name_ptr = name.into_bytes_with_nul(); let result = unsafe { BNBinaryViewAddExternalLibrary( self.as_ref().handle, - name_ptr.as_ref().as_ptr() as *const c_char, + name.as_cstr().as_ptr(), backing_file .map(|b| b.handle.as_ptr()) .unwrap_or(std::ptr::null_mut()), @@ -1549,7 +1479,7 @@ pub trait BinaryViewExt: BinaryViewBase { } // TODO: This is awful, rewrite this. - fn add_external_location( + fn add_external_location( &self, symbol: &Symbol, library: &ExternalLibrary, @@ -1557,7 +1487,6 @@ pub trait BinaryViewExt: BinaryViewBase { target_address: Option, target_is_auto: bool, ) -> Option> { - let target_symbol_name = target_symbol_name.into_bytes_with_nul(); let target_address_ptr = target_address .map(|a| a as *mut u64) .unwrap_or(std::ptr::null_mut()); @@ -1566,7 +1495,7 @@ pub trait BinaryViewExt: BinaryViewBase { self.as_ref().handle, symbol.handle, library.handle.as_ptr(), - target_symbol_name.as_ref().as_ptr() as *const c_char, + target_symbol_name.as_cstr().as_ptr(), target_address_ptr, target_is_auto, ) @@ -1607,14 +1536,9 @@ pub trait BinaryViewExt: BinaryViewBase { unsafe { BNAddBinaryViewTypeLibrary(self.as_ref().handle, library.as_raw()) } } - fn type_library_by_name(&self, name: S) -> Option { - let name = name.into_bytes_with_nul(); - let result = unsafe { - BNGetBinaryViewTypeLibrary( - self.as_ref().handle, - name.as_ref().as_ptr() as *const c_char, - ) - }; + fn type_library_by_name(&self, name: S) -> Option { + let result = + unsafe { BNGetBinaryViewTypeLibrary(self.as_ref().handle, name.as_cstr().as_ptr()) }; NonNull::new(result).map(|h| unsafe { TypeLibrary::from_raw(h) }) } @@ -1705,13 +1629,9 @@ pub trait BinaryViewExt: BinaryViewBase { /// contain a metadata key called "type_guids" which is a map /// Dict[string_guid, string_type_name] or /// Dict[string_guid, Tuple[string_type_name, type_library_name]] - fn import_type_by_guid(&self, guid: S) -> Option> { - let guid = guid.into_bytes_with_nul(); + fn import_type_by_guid(&self, guid: S) -> Option> { let result = unsafe { - BNBinaryViewImportTypeLibraryTypeByGuid( - self.as_ref().handle, - guid.as_ref().as_ptr() as *const c_char, - ) + BNBinaryViewImportTypeLibraryTypeByGuid(self.as_ref().handle, guid.as_cstr().as_ptr()) }; (!result.is_null()).then(|| unsafe { Type::ref_from_raw(result) }) } @@ -1853,9 +1773,9 @@ impl BinaryView { } pub fn from_path(meta: &mut FileMetadata, file_path: impl AsRef) -> Result> { - let file = file_path.as_ref().into_bytes_with_nul(); - let handle = - unsafe { BNCreateBinaryDataViewFromFilename(meta.handle, file.as_ptr() as *mut _) }; + let handle = unsafe { + BNCreateBinaryDataViewFromFilename(meta.handle, file_path.as_ref().as_cstr().as_ptr()) + }; if handle.is_null() { return Err(()); diff --git a/rust/src/calling_convention.rs b/rust/src/calling_convention.rs index 9b7507bc7..c30339e43 100644 --- a/rust/src/calling_convention.rs +++ b/rust/src/calling_convention.rs @@ -58,7 +58,7 @@ pub trait CallingConventionBase: Sync { pub fn register_calling_convention(arch: &A, name: N, cc: C) -> Ref> where A: Architecture, - N: BnStrCompatible, + N: AsCStr, C: 'static + CallingConventionBase, { struct CustomCallingConventionContext @@ -383,7 +383,6 @@ where ) } - let name = name.into_bytes_with_nul(); let raw = Box::into_raw(Box::new(CustomCallingConventionContext { raw_handle: std::ptr::null_mut(), cc, @@ -419,8 +418,8 @@ where }; unsafe { - let cc_name = name.as_ref().as_ptr() as *mut _; - let result = BNCreateCallingConvention(arch.as_ref().handle, cc_name, &mut cc); + let result = + BNCreateCallingConvention(arch.as_ref().handle, name.as_cstr().as_ptr(), &mut cc); assert!(!result.is_null()); diff --git a/rust/src/command.rs b/rust/src/command.rs index 98009a8fa..d4f36bb64 100644 --- a/rust/src/command.rs +++ b/rust/src/command.rs @@ -42,7 +42,7 @@ use std::os::raw::c_void; use crate::binary_view::BinaryView; use crate::function::Function; -use crate::string::BnStrCompatible; +use crate::string::AsCStr; /// The trait required for generic commands. See [register] for example usage. pub trait Command: 'static + Sync { @@ -95,7 +95,7 @@ where /// ``` pub fn register(name: S, desc: S, command: C) where - S: BnStrCompatible, + S: AsCStr, C: Command, { extern "C" fn cb_action(ctxt: *mut c_void, view: *mut BNBinaryView) @@ -126,18 +126,12 @@ where }) } - let name = name.into_bytes_with_nul(); - let desc = desc.into_bytes_with_nul(); - - let name_ptr = name.as_ref().as_ptr() as *mut _; - let desc_ptr = desc.as_ref().as_ptr() as *mut _; - let ctxt = Box::into_raw(Box::new(command)); unsafe { BNRegisterPluginCommand( - name_ptr, - desc_ptr, + name.as_cstr().as_ptr(), + desc.as_cstr().as_ptr(), Some(cb_action::), Some(cb_valid::), ctxt as *mut _, @@ -196,7 +190,7 @@ where /// ``` pub fn register_for_address(name: S, desc: S, command: C) where - S: BnStrCompatible, + S: AsCStr, C: AddressCommand, { extern "C" fn cb_action(ctxt: *mut c_void, view: *mut BNBinaryView, addr: u64) @@ -227,18 +221,12 @@ where }) } - let name = name.into_bytes_with_nul(); - let desc = desc.into_bytes_with_nul(); - - let name_ptr = name.as_ref().as_ptr() as *mut _; - let desc_ptr = desc.as_ref().as_ptr() as *mut _; - let ctxt = Box::into_raw(Box::new(command)); unsafe { BNRegisterPluginCommandForAddress( - name_ptr, - desc_ptr, + name.as_cstr().as_ptr(), + desc.as_cstr().as_ptr(), Some(cb_action::), Some(cb_valid::), ctxt as *mut _, @@ -298,7 +286,7 @@ where /// ``` pub fn register_for_range(name: S, desc: S, command: C) where - S: BnStrCompatible, + S: AsCStr, C: RangeCommand, { extern "C" fn cb_action(ctxt: *mut c_void, view: *mut BNBinaryView, addr: u64, len: u64) @@ -334,18 +322,12 @@ where }) } - let name = name.into_bytes_with_nul(); - let desc = desc.into_bytes_with_nul(); - - let name_ptr = name.as_ref().as_ptr() as *mut _; - let desc_ptr = desc.as_ref().as_ptr() as *mut _; - let ctxt = Box::into_raw(Box::new(command)); unsafe { BNRegisterPluginCommandForRange( - name_ptr, - desc_ptr, + name.as_cstr().as_ptr(), + desc.as_cstr().as_ptr(), Some(cb_action::), Some(cb_valid::), ctxt as *mut _, @@ -405,7 +387,7 @@ where /// ``` pub fn register_for_function(name: S, desc: S, command: C) where - S: BnStrCompatible, + S: AsCStr, C: FunctionCommand, { extern "C" fn cb_action(ctxt: *mut c_void, view: *mut BNBinaryView, func: *mut BNFunction) @@ -446,18 +428,12 @@ where }) } - let name = name.into_bytes_with_nul(); - let desc = desc.into_bytes_with_nul(); - - let name_ptr = name.as_ref().as_ptr() as *mut _; - let desc_ptr = desc.as_ref().as_ptr() as *mut _; - let ctxt = Box::into_raw(Box::new(command)); unsafe { BNRegisterPluginCommandForFunction( - name_ptr, - desc_ptr, + name.as_cstr().as_ptr(), + desc.as_cstr().as_ptr(), Some(cb_action::), Some(cb_valid::), ctxt as *mut _, diff --git a/rust/src/component.rs b/rust/src/component.rs index d03a6ace8..fba551c98 100644 --- a/rust/src/component.rs +++ b/rust/src/component.rs @@ -1,9 +1,9 @@ -use core::{ffi, mem, ptr}; +use core::{mem, ptr}; use crate::binary_view::{BinaryView, BinaryViewBase, BinaryViewExt}; use crate::function::Function; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; use crate::types::ComponentReferencedType; use crate::variable::DataVariable; @@ -39,7 +39,7 @@ impl ComponentBuilder { self } - pub fn name(mut self, name: S) -> Self { + pub fn name(mut self, name: S) -> Self { self.name = Some(BnString::new(name)); self } @@ -162,9 +162,8 @@ impl Component { unsafe { BnString::from_raw(result) } } - pub fn set_name(&self, name: S) { - let name = name.into_bytes_with_nul(); - unsafe { BNComponentSetName(self.as_raw(), name.as_ref().as_ptr() as *const ffi::c_char) } + pub fn set_name(&self, name: S) { + unsafe { BNComponentSetName(self.as_raw(), name.as_cstr().as_ptr()) } } /// The component that contains this component, if it exists. @@ -291,7 +290,7 @@ impl IntoComponentGuid for &Component { } } -impl IntoComponentGuid for S { +impl IntoComponentGuid for S { fn component_guid(self) -> BnString { BnString::new(self) } diff --git a/rust/src/custom_binary_view.rs b/rust/src/custom_binary_view.rs index fbd4cfc19..dcbfd2614 100644 --- a/rust/src/custom_binary_view.rs +++ b/rust/src/custom_binary_view.rs @@ -41,7 +41,7 @@ use crate::string::*; /// implementation of the `CustomBinaryViewType` must return. pub fn register_view_type(name: S, long_name: S, constructor: F) -> &'static T where - S: BnStrCompatible, + S: AsCStr, T: CustomBinaryViewType, F: FnOnce(BinaryViewType) -> T, { @@ -148,12 +148,6 @@ where }) } - let name = name.into_bytes_with_nul(); - let name_ptr = name.as_ref().as_ptr() as *mut _; - - let long_name = long_name.into_bytes_with_nul(); - let long_name_ptr = long_name.as_ref().as_ptr() as *mut _; - let ctxt = Box::leak(Box::new(MaybeUninit::zeroed())); let mut bn_obj = BNCustomBinaryViewType { @@ -167,7 +161,11 @@ where }; unsafe { - let handle = BNRegisterBinaryViewType(name_ptr, long_name_ptr, &mut bn_obj as *mut _); + let handle = BNRegisterBinaryViewType( + name.as_cstr().as_ptr(), + long_name.as_cstr().as_ptr(), + &mut bn_obj as *mut _, + ); if handle.is_null() { // avoid leaking the space allocated for the type, but also // avoid running its Drop impl (if any -- not that there should @@ -297,9 +295,8 @@ impl BinaryViewType { } /// Looks up a BinaryViewType by its short name - pub fn by_name(name: N) -> Result { - let bytes = name.into_bytes_with_nul(); - let handle = unsafe { BNGetBinaryViewTypeByName(bytes.as_ref().as_ptr() as *const _) }; + pub fn by_name(name: N) -> Result { + let handle = unsafe { BNGetBinaryViewTypeByName(name.as_cstr().as_ptr()) }; match handle.is_null() { false => Ok(unsafe { BinaryViewType::from_raw(handle) }), true => Err(()), diff --git a/rust/src/data_buffer.rs b/rust/src/data_buffer.rs index 5b4d6515a..4c5829fd2 100644 --- a/rust/src/data_buffer.rs +++ b/rust/src/data_buffer.rs @@ -121,7 +121,7 @@ impl DataBuffer { } pub fn from_escaped_string(value: &BnString) -> Self { - Self(unsafe { BNDecodeEscapedString(value.as_ptr()) }) + Self(unsafe { BNDecodeEscapedString(value.as_c_str().as_ptr()) }) } pub fn to_base64(&self) -> BnString { @@ -129,7 +129,7 @@ impl DataBuffer { } pub fn from_base64(value: &BnString) -> Self { - Self(unsafe { BNDecodeBase64(value.as_ptr()) }) + Self(unsafe { BNDecodeBase64(value.as_c_str().as_ptr()) }) } pub fn zlib_compress(&self) -> Self { diff --git a/rust/src/database.rs b/rust/src/database.rs index 6a43a963b..87bf21412 100644 --- a/rust/src/database.rs +++ b/rust/src/database.rs @@ -4,7 +4,7 @@ pub mod undo; use binaryninjacore_sys::*; use std::collections::HashMap; -use std::ffi::{c_char, c_void}; +use std::ffi::c_void; use std::fmt::Debug; use std::ptr::NonNull; @@ -15,7 +15,7 @@ use crate::database::snapshot::{Snapshot, SnapshotId}; use crate::file_metadata::FileMetadata; use crate::progress::ProgressExecutor; use crate::rc::{Array, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; pub struct Database { handle: NonNull, @@ -62,7 +62,7 @@ impl Database { unsafe { BNSetDatabaseCurrentSnapshot(self.handle.as_ptr(), id.0) } } - pub fn write_snapshot_data( + pub fn write_snapshot_data( &self, parents: &[SnapshotId], file: &BinaryView, @@ -80,7 +80,7 @@ impl Database { ) } - pub fn write_snapshot_data_with_progress( + pub fn write_snapshot_data_with_progress( &self, parents: &[SnapshotId], file: &BinaryView, @@ -88,12 +88,7 @@ impl Database { data: &KeyValueStore, auto_save: bool, progress: impl Into, - ) -> SnapshotId - where - N: BnStrCompatible, - { - let name_raw = name.into_bytes_with_nul(); - let name_ptr = name_raw.as_ref().as_ptr() as *const c_char; + ) -> SnapshotId { let boxed_progress = Box::new(progress.into()); let leaked_boxed_progress = Box::into_raw(boxed_progress); let new_id = unsafe { @@ -103,7 +98,7 @@ impl Database { parents.as_ptr() as *mut _, parents.len(), file.handle, - name_ptr, + name.as_cstr().as_ptr(), data.handle.as_ptr(), auto_save, leaked_boxed_progress as *mut c_void, @@ -133,10 +128,8 @@ impl Database { Err(()) } } - pub fn has_global(&self, key: S) -> bool { - let key_raw = key.into_bytes_with_nul(); - let key_ptr = key_raw.as_ref().as_ptr() as *const c_char; - unsafe { BNDatabaseHasGlobal(self.handle.as_ptr(), key_ptr) != 0 } + pub fn has_global(&self, key: S) -> bool { + unsafe { BNDatabaseHasGlobal(self.handle.as_ptr(), key.as_cstr().as_ptr()) != 0 } } /// Get a list of keys for all globals in the database @@ -156,35 +149,34 @@ impl Database { } /// Get a specific global by key - pub fn read_global(&self, key: S) -> Option { - let key_raw = key.into_bytes_with_nul(); - let key_ptr = key_raw.as_ref().as_ptr() as *const c_char; - let result = unsafe { BNReadDatabaseGlobal(self.handle.as_ptr(), key_ptr) }; + pub fn read_global(&self, key: S) -> Option { + let result = unsafe { BNReadDatabaseGlobal(self.handle.as_ptr(), key.as_cstr().as_ptr()) }; unsafe { NonNull::new(result).map(|_| BnString::from_raw(result)) } } /// Write a global into the database - pub fn write_global(&self, key: K, value: V) -> bool { - let key_raw = key.into_bytes_with_nul(); - let key_ptr = key_raw.as_ref().as_ptr() as *const c_char; - let value_raw = value.into_bytes_with_nul(); - let value_ptr = value_raw.as_ref().as_ptr() as *const c_char; - unsafe { BNWriteDatabaseGlobal(self.handle.as_ptr(), key_ptr, value_ptr) } + pub fn write_global(&self, key: K, value: V) -> bool { + unsafe { + BNWriteDatabaseGlobal( + self.handle.as_ptr(), + key.as_cstr().as_ptr(), + value.as_cstr().as_ptr(), + ) + } } /// Get a specific global by key, as a binary buffer - pub fn read_global_data(&self, key: S) -> Option { - let key_raw = key.into_bytes_with_nul(); - let key_ptr = key_raw.as_ref().as_ptr() as *const c_char; - let result = unsafe { BNReadDatabaseGlobalData(self.handle.as_ptr(), key_ptr) }; + pub fn read_global_data(&self, key: S) -> Option { + let result = + unsafe { BNReadDatabaseGlobalData(self.handle.as_ptr(), key.as_cstr().as_ptr()) }; NonNull::new(result).map(|_| DataBuffer::from_raw(result)) } /// Write a binary buffer into a global in the database - pub fn write_global_data(&self, key: K, value: &DataBuffer) -> bool { - let key_raw = key.into_bytes_with_nul(); - let key_ptr = key_raw.as_ref().as_ptr() as *const c_char; - unsafe { BNWriteDatabaseGlobalData(self.handle.as_ptr(), key_ptr, value.as_raw()) } + pub fn write_global_data(&self, key: K, value: &DataBuffer) -> bool { + unsafe { + BNWriteDatabaseGlobalData(self.handle.as_ptr(), key.as_cstr().as_ptr(), value.as_raw()) + } } /// Get the owning FileMetadata diff --git a/rust/src/database/kvs.rs b/rust/src/database/kvs.rs index 4b77bbdbf..ffe8c79bd 100644 --- a/rust/src/database/kvs.rs +++ b/rust/src/database/kvs.rs @@ -1,6 +1,6 @@ use crate::data_buffer::DataBuffer; use crate::rc::{Array, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; use binaryninjacore_sys::{ BNBeginKeyValueStoreNamespace, BNEndKeyValueStoreNamespace, BNFreeKeyValueStore, BNGetKeyValueStoreBuffer, BNGetKeyValueStoreDataSize, BNGetKeyValueStoreKeys, @@ -9,7 +9,6 @@ use binaryninjacore_sys::{ BNNewKeyValueStoreReference, BNSetKeyValueStoreBuffer, }; use std::collections::HashMap; -use std::ffi::c_char; use std::fmt::Debug; use std::ptr::NonNull; @@ -42,18 +41,17 @@ impl KeyValueStore { } /// Get the value for a single key - pub fn value(&self, key: S) -> Option { - let key_raw = key.into_bytes_with_nul(); - let key_ptr = key_raw.as_ref().as_ptr() as *const c_char; - let result = unsafe { BNGetKeyValueStoreBuffer(self.handle.as_ptr(), key_ptr) }; + pub fn value(&self, key: S) -> Option { + let result = + unsafe { BNGetKeyValueStoreBuffer(self.handle.as_ptr(), key.as_cstr().as_ptr()) }; NonNull::new(result).map(|_| DataBuffer::from_raw(result)) } /// Set the value for a single key - pub fn set_value(&self, key: S, value: &DataBuffer) -> bool { - let key_raw = key.into_bytes_with_nul(); - let key_ptr = key_raw.as_ref().as_ptr() as *const c_char; - unsafe { BNSetKeyValueStoreBuffer(self.handle.as_ptr(), key_ptr, value.as_raw()) } + pub fn set_value(&self, key: S, value: &DataBuffer) -> bool { + unsafe { + BNSetKeyValueStoreBuffer(self.handle.as_ptr(), key.as_cstr().as_ptr(), value.as_raw()) + } } /// Get the stored representation of the kvs @@ -64,10 +62,8 @@ impl KeyValueStore { } /// Begin storing new keys into a namespace - pub fn begin_namespace(&self, name: S) { - let name_raw = name.into_bytes_with_nul(); - let name_ptr = name_raw.as_ref().as_ptr() as *const c_char; - unsafe { BNBeginKeyValueStoreNamespace(self.handle.as_ptr(), name_ptr) } + pub fn begin_namespace(&self, name: S) { + unsafe { BNBeginKeyValueStoreNamespace(self.handle.as_ptr(), name.as_cstr().as_ptr()) } } /// End storing new keys into a namespace diff --git a/rust/src/database/snapshot.rs b/rust/src/database/snapshot.rs index bceceb7eb..3cd5d6a58 100644 --- a/rust/src/database/snapshot.rs +++ b/rust/src/database/snapshot.rs @@ -4,7 +4,7 @@ use crate::database::undo::UndoEntry; use crate::database::Database; use crate::progress::ProgressExecutor; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; use binaryninjacore_sys::{ BNFreeSnapshot, BNFreeSnapshotList, BNGetSnapshotChildren, BNGetSnapshotDatabase, BNGetSnapshotFileContents, BNGetSnapshotFileContentsHash, BNGetSnapshotFirstParent, @@ -14,7 +14,7 @@ use binaryninjacore_sys::{ BNSnapshot, BNSnapshotHasAncestor, BNSnapshotHasContents, BNSnapshotHasUndo, BNSnapshotStoreData, }; -use std::ffi::{c_char, c_void}; +use std::ffi::c_void; use std::fmt; use std::fmt::{Debug, Display, Formatter}; use std::ptr::NonNull; @@ -60,10 +60,8 @@ impl Snapshot { } /// Set the displayed snapshot name - pub fn set_name(&self, value: S) { - let value_raw = value.into_bytes_with_nul(); - let value_ptr = value_raw.as_ref().as_ptr() as *const c_char; - unsafe { BNSetSnapshotName(self.handle.as_ptr(), value_ptr) } + pub fn set_name(&self, value: S) { + unsafe { BNSetSnapshotName(self.handle.as_ptr(), value.as_cstr().as_ptr()) } } /// If the snapshot was the result of an auto-save diff --git a/rust/src/debuginfo.rs b/rust/src/debuginfo.rs index ece965b03..044b93c15 100644 --- a/rust/src/debuginfo.rs +++ b/rust/src/debuginfo.rs @@ -83,7 +83,7 @@ use crate::{ binary_view::BinaryView, platform::Platform, rc::*, - string::{raw_to_string, BnStrCompatible, BnString}, + string::{raw_to_string, AsCStr, BnString}, types::{NameAndType, Type}, }; @@ -115,9 +115,8 @@ impl DebugInfoParser { } /// Returns debug info parser of the given name, if it exists - pub fn from_name(name: S) -> Result, ()> { - let name = name.into_bytes_with_nul(); - let parser = unsafe { BNGetDebugInfoParserByName(name.as_ref().as_ptr() as *mut _) }; + pub fn from_name(name: S) -> Result, ()> { + let parser = unsafe { BNGetDebugInfoParserByName(name.as_cstr().as_ptr()) }; if parser.is_null() { Err(()) @@ -211,7 +210,7 @@ impl DebugInfoParser { // Registers a DebugInfoParser. See `binaryninja::debuginfo::DebugInfoParser` for more details. pub fn register(name: S, parser_callbacks: C) -> Ref where - S: BnStrCompatible, + S: AsCStr, C: CustomDebugInfoParser, { extern "C" fn cb_is_valid(ctxt: *mut c_void, view: *mut BNBinaryView) -> bool @@ -261,13 +260,11 @@ impl DebugInfoParser { }) } - let name = name.into_bytes_with_nul(); - let name_ptr = name.as_ref().as_ptr() as *mut _; let ctxt = Box::into_raw(Box::new(parser_callbacks)); unsafe { DebugInfoParser::from_raw(BNRegisterDebugInfoParser( - name_ptr, + name.as_cstr().as_ptr(), Some(cb_is_valid::), Some(cb_parse_info::), ctxt as *mut _, @@ -419,17 +416,10 @@ impl DebugInfo { } /// Returns all types within the parser - pub fn types_by_name(&self, parser_name: S) -> Vec { - let parser_name = parser_name.into_bytes_with_nul(); - + pub fn types_by_name(&self, parser_name: S) -> Vec { let mut count: usize = 0; - let debug_types_ptr = unsafe { - BNGetDebugTypes( - self.handle, - parser_name.as_ref().as_ptr() as *mut _, - &mut count, - ) - }; + let debug_types_ptr = + unsafe { BNGetDebugTypes(self.handle, parser_name.as_cstr().as_ptr(), &mut count) }; let result: Vec<_> = unsafe { std::slice::from_raw_parts_mut(debug_types_ptr, count) .iter() @@ -457,17 +447,10 @@ impl DebugInfo { } /// Returns all functions within the parser - pub fn functions_by_name(&self, parser_name: S) -> Vec { - let parser_name = parser_name.into_bytes_with_nul(); - + pub fn functions_by_name(&self, parser_name: S) -> Vec { let mut count: usize = 0; - let functions_ptr = unsafe { - BNGetDebugFunctions( - self.handle, - parser_name.as_ref().as_ptr() as *mut _, - &mut count, - ) - }; + let functions_ptr = + unsafe { BNGetDebugFunctions(self.handle, parser_name.as_cstr().as_ptr(), &mut count) }; let result: Vec = unsafe { std::slice::from_raw_parts_mut(functions_ptr, count) @@ -497,19 +480,13 @@ impl DebugInfo { } /// Returns all data variables within the parser - pub fn data_variables_by_name( + pub fn data_variables_by_name( &self, parser_name: S, ) -> Vec { - let parser_name = parser_name.into_bytes_with_nul(); - let mut count: usize = 0; let data_variables_ptr = unsafe { - BNGetDebugDataVariables( - self.handle, - parser_name.as_ref().as_ptr() as *mut _, - &mut count, - ) + BNGetDebugDataVariables(self.handle, parser_name.as_cstr().as_ptr(), &mut count) }; let result: Vec = unsafe { @@ -539,15 +516,12 @@ impl DebugInfo { result } - pub fn type_by_name(&self, parser_name: S, name: S) -> Option> { - let parser_name = parser_name.into_bytes_with_nul(); - let name = name.into_bytes_with_nul(); - + pub fn type_by_name(&self, parser_name: S, name: S) -> Option> { let result = unsafe { BNGetDebugTypeByName( self.handle, - parser_name.as_ref().as_ptr() as *mut _, - name.as_ref().as_ptr() as *mut _, + parser_name.as_cstr().as_ptr(), + name.as_cstr().as_ptr(), ) }; if !result.is_null() { @@ -557,18 +531,16 @@ impl DebugInfo { } } - pub fn get_data_variable_by_name( + pub fn get_data_variable_by_name( &self, parser_name: S, name: S, ) -> Option { - let parser_name = parser_name.into_bytes_with_nul(); - let name = name.into_bytes_with_nul(); let raw_named_var = unsafe { BNGetDebugDataVariableByName( self.handle, - parser_name.as_ref().as_ptr() as *mut _, - name.as_ref().as_ptr() as *mut _, + parser_name.as_cstr().as_ptr(), + name.as_cstr().as_ptr(), ) }; @@ -579,18 +551,13 @@ impl DebugInfo { } } - pub fn get_data_variable_by_address( + pub fn get_data_variable_by_address( &self, parser_name: S, address: u64, ) -> Option { - let parser_name = parser_name.into_bytes_with_nul(); let raw_named_var = unsafe { - BNGetDebugDataVariableByAddress( - self.handle, - parser_name.as_ref().as_ptr() as *mut _, - address, - ) + BNGetDebugDataVariableByAddress(self.handle, parser_name.as_cstr().as_ptr(), address) }; if !raw_named_var.is_null() { @@ -601,12 +568,10 @@ impl DebugInfo { } /// Returns a list of [`NameAndType`] where the `name` is the parser the type originates from. - pub fn get_types_by_name(&self, name: S) -> Vec { + pub fn get_types_by_name(&self, name: S) -> Vec { let mut count: usize = 0; - let name = name.into_bytes_with_nul(); - let raw_names_and_types_ptr = unsafe { - BNGetDebugTypesByName(self.handle, name.as_ref().as_ptr() as *mut _, &mut count) - }; + let raw_names_and_types_ptr = + unsafe { BNGetDebugTypesByName(self.handle, name.as_cstr().as_ptr(), &mut count) }; let raw_names_and_types: &[BNNameAndType] = unsafe { std::slice::from_raw_parts(raw_names_and_types_ptr, count) }; @@ -621,15 +586,10 @@ impl DebugInfo { } // The tuple is (DebugInfoParserName, address, type) - pub fn get_data_variables_by_name( - &self, - name: S, - ) -> Vec<(String, u64, Ref)> { - let name = name.into_bytes_with_nul(); - + pub fn get_data_variables_by_name(&self, name: S) -> Vec<(String, u64, Ref)> { let mut count: usize = 0; let raw_variables_and_names = unsafe { - BNGetDebugDataVariablesByName(self.handle, name.as_ref().as_ptr() as *mut _, &mut count) + BNGetDebugDataVariablesByName(self.handle, name.as_cstr().as_ptr(), &mut count) }; let variables_and_names: &[*mut BNDataVariableAndName] = @@ -676,96 +636,53 @@ impl DebugInfo { result } - pub fn remove_parser_info(&self, parser_name: S) -> bool { - let parser_name = parser_name.into_bytes_with_nul(); - - unsafe { BNRemoveDebugParserInfo(self.handle, parser_name.as_ref().as_ptr() as *mut _) } + pub fn remove_parser_info(&self, parser_name: S) -> bool { + unsafe { BNRemoveDebugParserInfo(self.handle, parser_name.as_cstr().as_ptr()) } } - pub fn remove_parser_types(&self, parser_name: S) -> bool { - let parser_name = parser_name.into_bytes_with_nul(); - - unsafe { BNRemoveDebugParserTypes(self.handle, parser_name.as_ref().as_ptr() as *mut _) } + pub fn remove_parser_types(&self, parser_name: S) -> bool { + unsafe { BNRemoveDebugParserTypes(self.handle, parser_name.as_cstr().as_ptr()) } } - pub fn remove_parser_functions(&self, parser_name: S) -> bool { - let parser_name = parser_name.into_bytes_with_nul(); - - unsafe { - BNRemoveDebugParserFunctions(self.handle, parser_name.as_ref().as_ptr() as *mut _) - } + pub fn remove_parser_functions(&self, parser_name: S) -> bool { + unsafe { BNRemoveDebugParserFunctions(self.handle, parser_name.as_cstr().as_ptr()) } } - pub fn remove_parser_data_variables(&self, parser_name: S) -> bool { - let parser_name = parser_name.into_bytes_with_nul(); - - unsafe { - BNRemoveDebugParserDataVariables(self.handle, parser_name.as_ref().as_ptr() as *mut _) - } + pub fn remove_parser_data_variables(&self, parser_name: S) -> bool { + unsafe { BNRemoveDebugParserDataVariables(self.handle, parser_name.as_cstr().as_ptr()) } } - pub fn remove_type_by_name(&self, parser_name: S, name: S) -> bool { - let parser_name = parser_name.into_bytes_with_nul(); - let name = name.into_bytes_with_nul(); - + pub fn remove_type_by_name(&self, parser_name: S, name: S) -> bool { unsafe { BNRemoveDebugTypeByName( self.handle, - parser_name.as_ref().as_ptr() as *mut _, - name.as_ref().as_ptr() as *mut _, + parser_name.as_cstr().as_ptr(), + name.as_cstr().as_ptr(), ) } } - pub fn remove_function_by_index( - &self, - parser_name: S, - index: usize, - ) -> bool { - let parser_name = parser_name.into_bytes_with_nul(); - - unsafe { - BNRemoveDebugFunctionByIndex( - self.handle, - parser_name.as_ref().as_ptr() as *mut _, - index, - ) - } + pub fn remove_function_by_index(&self, parser_name: S, index: usize) -> bool { + unsafe { BNRemoveDebugFunctionByIndex(self.handle, parser_name.as_cstr().as_ptr(), index) } } - pub fn remove_data_variable_by_address( - &self, - parser_name: S, - address: u64, - ) -> bool { - let parser_name = parser_name.into_bytes_with_nul(); - + pub fn remove_data_variable_by_address(&self, parser_name: S, address: u64) -> bool { unsafe { - BNRemoveDebugDataVariableByAddress( - self.handle, - parser_name.as_ref().as_ptr() as *mut _, - address, - ) + BNRemoveDebugDataVariableByAddress(self.handle, parser_name.as_cstr().as_ptr(), address) } } /// Adds a type scoped under the current parser's name to the debug info - pub fn add_type( - &self, - name: S, - new_type: &Type, - components: &[&str], - ) -> bool { - // SAFETY: Lifetime of `components` will live long enough, so passing as_ptr is safe. - let raw_components: Vec<_> = components.iter().map(|&c| c.as_ptr()).collect(); + pub fn add_type(&self, name: S, new_type: &Type, components: &[&str]) -> bool { + let components = components.iter().map(|c| c.as_cstr()).collect::>(); + let mut raw_components = components.iter().map(|c| c.as_ptr()).collect::>(); - let name = name.into_bytes_with_nul(); unsafe { BNAddDebugType( self.handle, - name.as_ref().as_ptr() as *mut _, + name.as_cstr().as_ptr(), new_type.handle, - raw_components.as_ptr() as *mut _, + raw_components.as_mut_ptr(), components.len(), ) } @@ -773,50 +690,36 @@ impl DebugInfo { /// Adds a function scoped under the current parser's name to the debug info pub fn add_function(&self, new_func: DebugFunctionInfo) -> bool { - let short_name_bytes = new_func.short_name.map(|name| name.into_bytes_with_nul()); - let short_name = short_name_bytes - .as_ref() - .map_or(std::ptr::null_mut() as *mut _, |name| name.as_ptr() as _); - let full_name_bytes = new_func.full_name.map(|name| name.into_bytes_with_nul()); - let full_name = full_name_bytes - .as_ref() - .map_or(std::ptr::null_mut() as *mut _, |name| name.as_ptr() as _); - let raw_name_bytes = new_func.raw_name.map(|name| name.into_bytes_with_nul()); - let raw_name = raw_name_bytes - .as_ref() - .map_or(std::ptr::null_mut() as *mut _, |name| name.as_ptr() as _); - - let mut components_array: Vec<*mut ::std::os::raw::c_char> = - Vec::with_capacity(new_func.components.len()); - - let mut local_variables_array: Vec = - Vec::with_capacity(new_func.local_variables.len()); + let short_name = new_func.short_name.as_ref().map(|name| name.as_cstr()); + let full_name = new_func.full_name.as_ref().map(|name| name.as_cstr()); + let raw_name = new_func.raw_name.as_ref().map(|name| name.as_cstr()); - unsafe { - for component in &new_func.components { - components_array.push(BNAllocString( - component.clone().into_bytes_with_nul().as_ptr() as _, - )); - } + let mut components = new_func + .components + .iter() + .map(|component| unsafe { BNAllocString(component.as_cstr().as_ptr()) }) + .collect::>(); - for local_variable in &new_func.local_variables { - local_variables_array.push(BNVariableNameAndType { - var: local_variable.variable.into(), - autoDefined: local_variable.auto_defined, - typeConfidence: local_variable.ty.confidence, - name: BNAllocString( - local_variable.name.clone().into_bytes_with_nul().as_ptr() as _ - ), - type_: local_variable.ty.contents.handle, - }); - } + let mut local_variables = new_func + .local_variables + .iter() + .map(|local_var| BNVariableNameAndType { + var: local_var.variable.into(), + autoDefined: local_var.auto_defined, + typeConfidence: local_var.ty.confidence, + name: unsafe { BNAllocString(local_var.name.as_cstr().as_ptr()) }, + type_: local_var.ty.contents.handle, + }) + .collect::>(); + let null_mut = std::ptr::null_mut(); + unsafe { let result = BNAddDebugFunction( self.handle, &mut BNDebugFunctionInfo { - shortName: short_name, - fullName: full_name, - rawName: raw_name, + shortName: short_name.map_or(null_mut, |name| name.as_ptr().cast_mut()), + fullName: full_name.map_or(null_mut, |name| name.as_ptr().cast_mut()), + rawName: raw_name.map_or(null_mut, |name| name.as_ptr().cast_mut()), address: new_func.address, type_: match new_func.type_ { Some(type_) => type_.handle, @@ -826,18 +729,18 @@ impl DebugInfo { Some(platform) => platform.handle, _ => std::ptr::null_mut(), }, - components: components_array.as_ptr() as _, + components: components.as_mut_ptr(), componentN: new_func.components.len(), - localVariables: local_variables_array.as_ptr() as _, - localVariableN: local_variables_array.len(), + localVariables: local_variables.as_mut_ptr(), + localVariableN: local_variables.len(), }, ); - for i in components_array { + for i in components { BNFreeString(i); } - for i in &local_variables_array { + for i in &local_variables { BNFreeString(i.name); } result @@ -845,43 +748,26 @@ impl DebugInfo { } /// Adds a data variable scoped under the current parser's name to the debug info - pub fn add_data_variable( + pub fn add_data_variable( &self, address: u64, t: &Type, name: Option, components: &[&str], ) -> bool { - let mut components_array: Vec<*const ::std::os::raw::c_char> = - Vec::with_capacity(components.len()); - for component in components { - components_array.push(component.as_ptr() as _); - } + let components = components.iter().map(|s| s.as_cstr()).collect::>(); + let mut components_array = components.iter().map(|s| s.as_ptr()).collect::>(); + let name_ptr = name.map_or(std::ptr::null(), |n| n.as_cstr().as_ptr()); - match name { - Some(name) => { - let name = name.into_bytes_with_nul(); - unsafe { - BNAddDebugDataVariable( - self.handle, - address, - t.handle, - name.as_ref().as_ptr() as *mut _, - components.as_ptr() as _, - components.len(), - ) - } - } - None => unsafe { - BNAddDebugDataVariable( - self.handle, - address, - t.handle, - std::ptr::null_mut(), - components.as_ptr() as _, - components.len(), - ) - }, + unsafe { + BNAddDebugDataVariable( + self.handle, + address, + t.handle, + name_ptr, + components_array.as_mut_ptr(), + components_array.len(), + ) } } diff --git a/rust/src/demangle.rs b/rust/src/demangle.rs index 6e303fac0..ea08064ca 100644 --- a/rust/src/demangle.rs +++ b/rust/src/demangle.rs @@ -19,27 +19,25 @@ use std::ffi::{c_char, c_void}; use crate::architecture::CoreArchitecture; use crate::binary_view::BinaryView; -use crate::string::{raw_to_string, BnStrCompatible, BnString}; +use crate::string::{raw_to_string, AsCStr, BnString}; use crate::types::{QualifiedName, Type}; use crate::rc::*; pub type Result = std::result::Result; -pub fn demangle_generic( +pub fn demangle_generic( arch: &CoreArchitecture, mangled_name: S, view: Option<&BinaryView>, simplify: bool, ) -> Option<(QualifiedName, Option>)> { - let mangled_name_bwn = mangled_name.into_bytes_with_nul(); - let mangled_name_ptr = mangled_name_bwn.as_ref(); let mut out_type: *mut BNType = std::ptr::null_mut(); let mut out_name = BNQualifiedName::default(); let res = unsafe { BNDemangleGeneric( arch.handle, - mangled_name_ptr.as_ptr() as *const c_char, + mangled_name.as_cstr().as_ptr(), &mut out_type, &mut out_name, view.map(|v| v.handle).unwrap_or(std::ptr::null_mut()), @@ -58,14 +56,12 @@ pub fn demangle_generic( } } -pub fn demangle_llvm(mangled_name: S, simplify: bool) -> Option { - let mangled_name_bwn = mangled_name.into_bytes_with_nul(); - let mangled_name_ptr = mangled_name_bwn.as_ref(); +pub fn demangle_llvm(mangled_name: S, simplify: bool) -> Option { let mut out_name: *mut *mut std::os::raw::c_char = std::ptr::null_mut(); let mut out_size: usize = 0; let res = unsafe { BNDemangleLLVM( - mangled_name_ptr.as_ptr() as *const c_char, + mangled_name.as_cstr().as_ptr(), &mut out_name, &mut out_size, simplify, @@ -87,20 +83,18 @@ pub fn demangle_llvm(mangled_name: S, simplify: bool) -> Opt } } -pub fn demangle_gnu3( +pub fn demangle_gnu3( arch: &CoreArchitecture, mangled_name: S, simplify: bool, ) -> Option<(QualifiedName, Option>)> { - let mangled_name_bwn = mangled_name.into_bytes_with_nul(); - let mangled_name_ptr = mangled_name_bwn.as_ref(); let mut out_type: *mut BNType = std::ptr::null_mut(); let mut out_name: *mut *mut std::os::raw::c_char = std::ptr::null_mut(); let mut out_size: usize = 0; let res = unsafe { BNDemangleGNU3( arch.handle, - mangled_name_ptr.as_ptr() as *const c_char, + mangled_name.as_cstr().as_ptr(), &mut out_type, &mut out_name, &mut out_size, @@ -128,21 +122,18 @@ pub fn demangle_gnu3( } } -pub fn demangle_ms( +pub fn demangle_ms( arch: &CoreArchitecture, mangled_name: S, simplify: bool, ) -> Option<(QualifiedName, Option>)> { - let mangled_name_bwn = mangled_name.into_bytes_with_nul(); - let mangled_name_ptr = mangled_name_bwn.as_ref(); - let mut out_type: *mut BNType = std::ptr::null_mut(); let mut out_name: *mut *mut std::os::raw::c_char = std::ptr::null_mut(); let mut out_size: usize = 0; let res = unsafe { BNDemangleMS( arch.handle, - mangled_name_ptr.as_ptr() as *const c_char, + mangled_name.as_cstr().as_ptr(), &mut out_type, &mut out_name, &mut out_size, @@ -187,19 +178,16 @@ impl Demangler { unsafe { Array::::new(demanglers, count, ()) } } - pub fn is_mangled_string(&self, name: S) -> bool { - let bytes = name.into_bytes_with_nul(); - unsafe { BNIsDemanglerMangledName(self.handle, bytes.as_ref().as_ptr() as *const _) } + pub fn is_mangled_string(&self, name: S) -> bool { + unsafe { BNIsDemanglerMangledName(self.handle, name.as_cstr().as_ptr()) } } - pub fn demangle( + pub fn demangle( &self, arch: &CoreArchitecture, name: S, view: Option<&BinaryView>, ) -> Option<(QualifiedName, Option>)> { - let name_bytes = name.into_bytes_with_nul(); - let mut out_type = std::ptr::null_mut(); let mut out_var_name = BNQualifiedName::default(); @@ -212,7 +200,7 @@ impl Demangler { BNDemanglerDemangle( self.handle, arch.handle, - name_bytes.as_ref().as_ptr() as *const _, + name.as_cstr().as_ptr(), &mut out_type, &mut out_var_name, view_ptr, @@ -236,9 +224,8 @@ impl Demangler { unsafe { BnString::from_raw(BNGetDemanglerName(self.handle)) } } - pub fn from_name(name: S) -> Option { - let name_bytes = name.into_bytes_with_nul(); - let demangler = unsafe { BNGetDemanglerByName(name_bytes.as_ref().as_ptr() as *const _) }; + pub fn from_name(name: S) -> Option { + let demangler = unsafe { BNGetDemanglerByName(name.as_cstr().as_ptr()) }; if demangler.is_null() { None } else { @@ -248,7 +235,7 @@ impl Demangler { pub fn register(name: S, demangler: C) -> Self where - S: BnStrCompatible, + S: AsCStr, C: CustomDemangler, { extern "C" fn cb_is_mangled_string(ctxt: *mut c_void, name: *const c_char) -> bool @@ -308,8 +295,6 @@ impl Demangler { }) } - let name = name.into_bytes_with_nul(); - let name_ptr = name.as_ref().as_ptr() as *mut _; let ctxt = Box::into_raw(Box::new(demangler)); let callbacks = BNDemanglerCallbacks { @@ -321,7 +306,7 @@ impl Demangler { unsafe { Demangler::from_raw(BNRegisterDemangler( - name_ptr, + name.as_cstr().as_ptr(), Box::leak(Box::new(callbacks)), )) } diff --git a/rust/src/download_provider.rs b/rust/src/download_provider.rs index 1e61c87de..6cc2a6a51 100644 --- a/rust/src/download_provider.rs +++ b/rust/src/download_provider.rs @@ -1,6 +1,6 @@ use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; use crate::settings::Settings; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; use binaryninjacore_sys::*; use std::collections::HashMap; use std::ffi::{c_void, CStr}; @@ -13,12 +13,8 @@ pub struct DownloadProvider { } impl DownloadProvider { - pub fn get(name: S) -> Option { - let result = unsafe { - BNGetDownloadProviderByName( - name.into_bytes_with_nul().as_ref().as_ptr() as *const c_char - ) - }; + pub fn get(name: S) -> Option { + let result = unsafe { BNGetDownloadProviderByName(name.as_cstr().as_ptr()) }; if result.is_null() { return None; } @@ -130,7 +126,7 @@ impl DownloadInstance { } } - pub fn perform_request( + pub fn perform_request( &mut self, url: S, callbacks: DownloadInstanceOutputCallbacks, @@ -146,7 +142,7 @@ impl DownloadInstance { let result = unsafe { BNPerformDownloadRequest( self.handle, - url.into_bytes_with_nul().as_ref().as_ptr() as *const c_char, + url.as_cstr().as_ptr(), &mut cbs as *mut BNDownloadInstanceOutputCallbacks, ) }; @@ -196,10 +192,10 @@ impl DownloadInstance { } pub fn perform_custom_request< - M: BnStrCompatible, - U: BnStrCompatible, - HK: BnStrCompatible, - HV: BnStrCompatible, + M: AsCStr, + U: AsCStr, + HK: AsCStr, + HV: AsCStr, I: IntoIterator, >( &mut self, @@ -208,20 +204,13 @@ impl DownloadInstance { headers: I, callbacks: DownloadInstanceInputOutputCallbacks, ) -> Result { - let mut header_keys = vec![]; - let mut header_values = vec![]; - for (key, value) in headers { - header_keys.push(key.into_bytes_with_nul()); - header_values.push(value.into_bytes_with_nul()); - } + let (keys, values): (Vec<_>, Vec<_>) = headers.into_iter().unzip(); - let mut header_key_ptrs = vec![]; - let mut header_value_ptrs = vec![]; + let header_keys = keys.iter().map(|k| k.as_cstr()).collect::>(); + let header_values = values.iter().map(|v| v.as_cstr()).collect::>(); - for (key, value) in header_keys.iter().zip(header_values.iter()) { - header_key_ptrs.push(key.as_ref().as_ptr() as *const c_char); - header_value_ptrs.push(value.as_ref().as_ptr() as *const c_char); - } + let header_key_ptrs = header_keys.iter().map(|k| k.as_ptr()).collect::>(); + let header_value_ptrs = header_values.iter().map(|v| v.as_ptr()).collect::>(); let callbacks = Box::into_raw(Box::new(callbacks)); let mut cbs = BNDownloadInstanceInputOutputCallbacks { @@ -238,8 +227,8 @@ impl DownloadInstance { let result = unsafe { BNPerformCustomRequest( self.handle, - method.into_bytes_with_nul().as_ref().as_ptr() as *const c_char, - url.into_bytes_with_nul().as_ref().as_ptr() as *const c_char, + method.as_cstr().as_ptr(), + url.as_cstr().as_ptr(), header_key_ptrs.len() as u64, header_key_ptrs.as_ptr(), header_value_ptrs.as_ptr(), diff --git a/rust/src/enterprise.rs b/rust/src/enterprise.rs index 235a0e0ac..7f874cbe3 100644 --- a/rust/src/enterprise.rs +++ b/rust/src/enterprise.rs @@ -1,5 +1,5 @@ use crate::rc::Array; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; use std::marker::PhantomData; use std::time::{Duration, SystemTime, UNIX_EPOCH}; use thiserror::Error; @@ -94,13 +94,8 @@ pub fn server_url() -> BnString { unsafe { BnString::from_raw(binaryninjacore_sys::BNGetEnterpriseServerUrl()) } } -pub fn set_server_url(url: S) -> Result<(), ()> { - let url = url.into_bytes_with_nul(); - let result = unsafe { - binaryninjacore_sys::BNSetEnterpriseServerUrl( - url.as_ref().as_ptr() as *const std::os::raw::c_char - ) - }; +pub fn set_server_url(url: S) -> Result<(), ()> { + let result = unsafe { binaryninjacore_sys::BNSetEnterpriseServerUrl(url.as_cstr().as_ptr()) }; if result { Ok(()) } else { @@ -153,25 +148,22 @@ pub fn is_server_license_still_activated() -> bool { pub fn authenticate_server_with_credentials(username: U, password: P, remember: bool) -> bool where - U: BnStrCompatible, - P: BnStrCompatible, + U: AsCStr, + P: AsCStr, { - let username = username.into_bytes_with_nul(); - let password = password.into_bytes_with_nul(); unsafe { binaryninjacore_sys::BNAuthenticateEnterpriseServerWithCredentials( - username.as_ref().as_ptr() as *const std::os::raw::c_char, - password.as_ref().as_ptr() as *const std::os::raw::c_char, + username.as_cstr().as_ptr(), + password.as_cstr().as_ptr(), remember, ) } } -pub fn authenticate_server_with_method(method: S, remember: bool) -> bool { - let method = method.into_bytes_with_nul(); +pub fn authenticate_server_with_method(method: S, remember: bool) -> bool { unsafe { binaryninjacore_sys::BNAuthenticateEnterpriseServerWithMethod( - method.as_ref().as_ptr() as *const std::os::raw::c_char, + method.as_cstr().as_ptr(), remember, ) } diff --git a/rust/src/external_library.rs b/rust/src/external_library.rs index 2b3594b64..3318b1828 100644 --- a/rust/src/external_library.rs +++ b/rust/src/external_library.rs @@ -1,9 +1,8 @@ use crate::project::file::ProjectFile; use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; use crate::symbol::Symbol; use binaryninjacore_sys::*; -use std::ffi::c_char; use std::fmt::Debug; use std::ptr::NonNull; @@ -167,10 +166,8 @@ impl ExternalLocation { /// Set the symbol pointed to by this ExternalLocation. /// ExternalLocations must have a valid target address and/or symbol set. - pub fn set_target_symbol(&self, symbol: Option) -> bool { - let symbol = symbol - .map(|x| x.into_bytes_with_nul().as_ref().as_ptr() as *const c_char) - .unwrap_or(std::ptr::null_mut()); + pub fn set_target_symbol(&self, symbol: Option) -> bool { + let symbol = symbol.map_or(std::ptr::null(), |x| x.as_cstr().as_ptr()); unsafe { BNExternalLocationSetTargetSymbol(self.handle.as_ptr(), symbol) } } } diff --git a/rust/src/file_metadata.rs b/rust/src/file_metadata.rs index 8776cfba2..487dc492a 100644 --- a/rust/src/file_metadata.rs +++ b/rust/src/file_metadata.rs @@ -52,7 +52,7 @@ impl FileMetadata { Self::ref_from_raw(unsafe { BNCreateFileMetadata() }) } - pub fn with_filename(name: S) -> Ref { + pub fn with_filename(name: S) -> Ref { let ret = FileMetadata::new(); ret.set_filename(name); ret @@ -75,12 +75,8 @@ impl FileMetadata { } } - pub fn set_filename(&self, name: S) { - let name = name.into_bytes_with_nul(); - - unsafe { - BNSetFilename(self.handle, name.as_ref().as_ptr() as *mut _); - } + pub fn set_filename(&self, name: S) { + unsafe { BNSetFilename(self.handle, name.as_cstr().as_ptr()) } } pub fn modified(&self) -> bool { @@ -107,10 +103,8 @@ impl FileMetadata { self.is_database_backed_for_view_type("") } - pub fn is_database_backed_for_view_type(&self, view_type: S) -> bool { - let view_type = view_type.into_bytes_with_nul(); - - unsafe { BNIsBackedByDatabase(self.handle, view_type.as_ref().as_ptr() as *const _) } + pub fn is_database_backed_for_view_type(&self, view_type: S) -> bool { + unsafe { BNIsBackedByDatabase(self.handle, view_type.as_cstr().as_ptr()) } } pub fn run_undoable_transaction Result, T, E>( @@ -135,18 +129,12 @@ impl FileMetadata { unsafe { BnString::from_raw(BNBeginUndoActions(self.handle, anonymous_allowed)) } } - pub fn commit_undo_actions(&self, id: S) { - let id = id.into_bytes_with_nul(); - unsafe { - BNCommitUndoActions(self.handle, id.as_ref().as_ptr() as *const _); - } + pub fn commit_undo_actions(&self, id: S) { + unsafe { BNCommitUndoActions(self.handle, id.as_cstr().as_ptr()) } } - pub fn revert_undo_actions(&self, id: S) { - let id = id.into_bytes_with_nul(); - unsafe { - BNRevertUndoActions(self.handle, id.as_ref().as_ptr() as *const _); - } + pub fn revert_undo_actions(&self, id: S) { + unsafe { BNRevertUndoActions(self.handle, id.as_cstr().as_ptr()) } } pub fn undo(&self) { @@ -169,11 +157,9 @@ impl FileMetadata { unsafe { BNGetCurrentOffset(self.handle) } } - pub fn navigate_to(&self, view: S, offset: u64) -> Result<(), ()> { - let view = view.into_bytes_with_nul(); - + pub fn navigate_to(&self, view: S, offset: u64) -> Result<(), ()> { unsafe { - if BNNavigate(self.handle, view.as_ref().as_ptr() as *const _, offset) { + if BNNavigate(self.handle, view.as_cstr().as_ptr(), offset) { Ok(()) } else { Err(()) @@ -181,11 +167,9 @@ impl FileMetadata { } } - pub fn view_of_type(&self, view: S) -> Option> { - let view = view.into_bytes_with_nul(); - + pub fn view_of_type(&self, view: S) -> Option> { unsafe { - let raw_view_ptr = BNGetFileViewOfType(self.handle, view.as_ref().as_ptr() as *const _); + let raw_view_ptr = BNGetFileViewOfType(self.handle, view.as_cstr().as_ptr()); match raw_view_ptr.is_null() { false => Some(BinaryView::ref_from_raw(raw_view_ptr)), true => None, @@ -202,26 +186,26 @@ impl FileMetadata { } // TODO: filename can be AsRef imo - pub fn create_database(&self, filename: S) -> bool { - let filename = filename.into_bytes_with_nul(); - let filename_ptr = filename.as_ref().as_ptr() as *mut _; - + pub fn create_database(&self, filename: S) -> bool { // Databases are created with the root view (Raw). let Some(raw_view) = self.view_of_type("Raw") else { return false; }; - unsafe { BNCreateDatabase(raw_view.handle, filename_ptr, ptr::null_mut()) } + unsafe { + BNCreateDatabase( + raw_view.handle, + filename.as_cstr().as_ptr(), + ptr::null_mut(), + ) + } } - pub fn create_database_with_progress( + pub fn create_database_with_progress( &self, filename: S, progress: impl Into, ) -> bool { - let filename = filename.into_bytes_with_nul(); - let filename_ptr = filename.as_ref().as_ptr() as *mut _; - // Databases are created with the root view (Raw). let Some(raw_view) = self.view_of_type("Raw") else { return false; @@ -232,7 +216,7 @@ impl FileMetadata { let success = unsafe { BNCreateDatabaseWithProgress( raw_view.handle, - filename_ptr, + filename.as_cstr().as_ptr(), leaked_boxed_progress as *mut c_void, Some(ProgressExecutor::cb_execute), ptr::null_mut(), @@ -251,14 +235,12 @@ impl FileMetadata { unsafe { BNSaveAutoSnapshot(raw_view.handle, ptr::null_mut() as *mut _) } } - pub fn open_database_for_configuration( + pub fn open_database_for_configuration( &self, filename: S, ) -> Result, ()> { - let filename = filename.into_bytes_with_nul(); unsafe { - let bv = - BNOpenDatabaseForConfiguration(self.handle, filename.as_ref().as_ptr() as *const _); + let bv = BNOpenDatabaseForConfiguration(self.handle, filename.as_cstr().as_ptr()); if bv.is_null() { Err(()) @@ -268,11 +250,8 @@ impl FileMetadata { } } - pub fn open_database(&self, filename: S) -> Result, ()> { - let filename = filename.into_bytes_with_nul(); - let filename_ptr = filename.as_ref().as_ptr() as *mut _; - - let view = unsafe { BNOpenExistingDatabase(self.handle, filename_ptr) }; + pub fn open_database(&self, filename: S) -> Result, ()> { + let view = unsafe { BNOpenExistingDatabase(self.handle, filename.as_cstr().as_ptr()) }; if view.is_null() { Err(()) @@ -281,19 +260,17 @@ impl FileMetadata { } } - pub fn open_database_with_progress( + pub fn open_database_with_progress( &self, filename: S, progress: impl Into, ) -> Result, ()> { - let filename = filename.into_bytes_with_nul(); - let filename_ptr = filename.as_ref().as_ptr() as *mut _; let boxed_progress = Box::new(progress.into()); let leaked_boxed_progress = Box::into_raw(boxed_progress); let view = unsafe { BNOpenExistingDatabaseWithProgress( self.handle, - filename_ptr, + filename.as_cstr().as_ptr(), leaked_boxed_progress as *mut c_void, Some(ProgressExecutor::cb_execute), ) diff --git a/rust/src/function.rs b/rust/src/function.rs index a4c4a1adb..c0d43cfd0 100644 --- a/rust/src/function.rs +++ b/rust/src/function.rs @@ -332,12 +332,8 @@ impl Function { unsafe { BnString::from_raw(BNGetFunctionComment(self.handle)) } } - pub fn set_comment(&self, comment: S) { - let raw = comment.into_bytes_with_nul(); - - unsafe { - BNSetFunctionComment(self.handle, raw.as_ref().as_ptr() as *mut _); - } + pub fn set_comment(&self, comment: S) { + unsafe { BNSetFunctionComment(self.handle, comment.as_cstr().as_ptr()) } } pub fn set_can_return_auto>>(&self, can_return: T) { @@ -354,12 +350,8 @@ impl Function { unsafe { BnString::from_raw(BNGetCommentForAddress(self.handle, addr)) } } - pub fn set_comment_at(&self, addr: u64, comment: S) { - let raw = comment.into_bytes_with_nul(); - - unsafe { - BNSetCommentForAddress(self.handle, addr, raw.as_ref().as_ptr() as *mut _); - } + pub fn set_comment_at(&self, addr: u64, comment: S) { + unsafe { BNSetCommentForAddress(self.handle, addr, comment.as_cstr().as_ptr()) } } /// All comments in the function @@ -1061,7 +1053,7 @@ impl Function { /// let crash = bv.create_tag_type("Crashes", "🎯"); /// fun.add_tag(&crash, "Nullpointer dereference", Some(0x1337), false, None); /// ``` - pub fn add_tag( + pub fn add_tag( &self, tag_type: &TagType, data: S, @@ -1658,20 +1650,18 @@ impl Function { /// * `display_type` - Desired display type /// * `arch` - (optional) Architecture of the instruction or IL line containing the token /// * `enum_display_typeid` - (optional) Whenever passing EnumDisplayType to `display_type`, passing a type ID here will specify the Enumeration display type. Must be a valid type ID and resolve to an enumeration type. - pub fn set_int_display_type( + pub fn set_int_display_type( &self, instr_addr: u64, value: u64, operand: usize, display_type: IntegerDisplayType, arch: Option, - enum_display_typeid: Option, + enum_display_typeid: Option, ) { let arch = arch.unwrap_or_else(|| self.arch()); - let enum_display_typeid = enum_display_typeid.map(BnStrCompatible::into_bytes_with_nul); - let enum_display_typeid_ptr = enum_display_typeid - .map(|x| x.as_ref().as_ptr() as *const c_char) - .unwrap_or(std::ptr::null()); + let enum_display_typeid_ptr = + enum_display_typeid.map_or(std::ptr::null(), |x| x.as_cstr().as_ptr()); unsafe { BNSetIntegerConstantDisplayType( self.handle, diff --git a/rust/src/high_level_il/operation.rs b/rust/src/high_level_il/operation.rs index f7a4b5be3..8031f7b92 100644 --- a/rust/src/high_level_il/operation.rs +++ b/rust/src/high_level_il/operation.rs @@ -1,12 +1,10 @@ -use core::ffi; - use binaryninjacore_sys::*; use super::HighLevelILLiftedInstruction; use crate::architecture::CoreIntrinsic; use crate::function::Function; use crate::rc::Ref; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; use crate::variable::{ConstantData, SSAVariable, Variable}; #[derive(Clone, Debug, PartialEq, Eq)] @@ -20,14 +18,9 @@ impl GotoLabel { unsafe { BnString::from_raw(BNGetGotoLabelName(self.function.handle, self.target)) } } - fn set_name(&self, name: S) { - let raw = name.into_bytes_with_nul(); + fn set_name(&self, name: S) { unsafe { - BNSetUserGotoLabelName( - self.function.handle, - self.target, - raw.as_ref().as_ptr() as *const ffi::c_char, - ) + BNSetUserGotoLabelName(self.function.handle, self.target, name.as_cstr().as_ptr()) } } } @@ -318,7 +311,7 @@ impl LiftedLabel { self.target.name() } - pub fn set_name(&self, name: S) { + pub fn set_name(&self, name: S) { self.target.set_name(name) } } diff --git a/rust/src/interaction.rs b/rust/src/interaction.rs index 151e9f7c6..81e0270bf 100644 --- a/rust/src/interaction.rs +++ b/rust/src/interaction.rs @@ -21,7 +21,7 @@ use std::path::PathBuf; use crate::binary_view::BinaryView; use crate::rc::Ref; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; pub fn get_text_line_input(prompt: &str, title: &str) -> Option { let mut value: *mut c_char = std::ptr::null_mut(); @@ -29,8 +29,8 @@ pub fn get_text_line_input(prompt: &str, title: &str) -> Option { let result = unsafe { BNGetTextLineInput( &mut value, - prompt.into_bytes_with_nul().as_ptr() as *mut _, - title.into_bytes_with_nul().as_ptr() as *mut _, + prompt.as_cstr().as_ptr(), + title.as_cstr().as_ptr(), ) }; if !result { @@ -46,8 +46,8 @@ pub fn get_integer_input(prompt: &str, title: &str) -> Option { let result = unsafe { BNGetIntegerInput( &mut value, - prompt.into_bytes_with_nul().as_ptr() as *mut _, - title.into_bytes_with_nul().as_ptr() as *mut _, + prompt.as_cstr().as_ptr(), + title.as_cstr().as_ptr(), ) }; @@ -64,8 +64,8 @@ pub fn get_address_input(prompt: &str, title: &str) -> Option { let result = unsafe { BNGetAddressInput( &mut value, - prompt.into_bytes_with_nul().as_ptr() as *mut _, - title.into_bytes_with_nul().as_ptr() as *mut _, + prompt.as_cstr().as_ptr(), + title.as_cstr().as_ptr(), std::ptr::null_mut(), 0, ) @@ -84,8 +84,8 @@ pub fn get_open_filename_input(prompt: &str, extension: &str) -> Option let result = unsafe { BNGetOpenFileNameInput( &mut value, - prompt.into_bytes_with_nul().as_ptr() as *mut _, - extension.into_bytes_with_nul().as_ptr() as *mut _, + prompt.as_cstr().as_ptr(), + extension.as_cstr().as_ptr(), ) }; if !result { @@ -106,9 +106,9 @@ pub fn get_save_filename_input( let result = unsafe { BNGetSaveFileNameInput( &mut value, - prompt.into_bytes_with_nul().as_ptr() as *mut _, - extension.into_bytes_with_nul().as_ptr() as *mut _, - default_name.into_bytes_with_nul().as_ptr() as *mut _, + prompt.as_cstr().as_ptr(), + extension.as_cstr().as_ptr(), + default_name.as_cstr().as_ptr(), ) }; if !result { @@ -125,8 +125,8 @@ pub fn get_directory_name_input(prompt: &str, default_name: &str) -> Option MessageBoxButtonResult { unsafe { BNShowMessageBox( - title.into_bytes_with_nul().as_ptr() as *mut _, - text.into_bytes_with_nul().as_ptr() as *mut _, + title.as_cstr().as_ptr(), + text.as_cstr().as_ptr(), buttons, icon, ) @@ -210,7 +210,7 @@ impl FormInputBuilder { let mut result = unsafe { std::mem::zeroed::() }; result.type_ = BNFormInputFieldType::LabelFormField; result.hasDefault = false; - result.prompt = text.as_ref().as_ptr() as *const c_char; + result.prompt = text.as_ptr(); self.fields.push(result); self.data.push(FormData::Label { _text: text }); @@ -233,10 +233,10 @@ impl FormInputBuilder { let mut result = unsafe { std::mem::zeroed::() }; result.type_ = BNFormInputFieldType::TextLineFormField; - result.prompt = prompt.as_ref().as_ptr() as *const c_char; + result.prompt = prompt.as_ptr(); result.hasDefault = default.is_some(); if let Some(ref default) = default { - result.stringDefault = default.as_ref().as_ptr() as *const c_char; + result.stringDefault = default.as_ptr(); } self.fields.push(result); @@ -254,10 +254,10 @@ impl FormInputBuilder { let mut result = unsafe { std::mem::zeroed::() }; result.type_ = BNFormInputFieldType::MultilineTextFormField; - result.prompt = prompt.as_ref().as_ptr() as *const c_char; + result.prompt = prompt.as_ptr(); result.hasDefault = default.is_some(); if let Some(ref default) = default { - result.stringDefault = default.as_ref().as_ptr() as *const c_char; + result.stringDefault = default.as_ptr(); } self.fields.push(result); @@ -274,7 +274,7 @@ impl FormInputBuilder { let mut result = unsafe { std::mem::zeroed::() }; result.type_ = BNFormInputFieldType::IntegerFormField; - result.prompt = prompt.as_ref().as_ptr() as *const c_char; + result.prompt = prompt.as_ptr(); result.hasDefault = default.is_some(); if let Some(default) = default { result.intDefault = default; @@ -297,7 +297,7 @@ impl FormInputBuilder { let mut result = unsafe { std::mem::zeroed::() }; result.type_ = BNFormInputFieldType::AddressFormField; - result.prompt = prompt.as_ref().as_ptr() as *const c_char; + result.prompt = prompt.as_ptr(); if let Some(view) = view { // the view is being moved into result, there is no need to clone // and drop is intentionally being avoided with `Ref::into_raw` @@ -317,15 +317,12 @@ impl FormInputBuilder { /// Form Field: Prompt for a choice from provided options pub fn choice_field(mut self, prompt: &str, choices: &[&str], default: Option) -> Self { let prompt = BnString::new(prompt); - let choices: Vec = choices.iter().map(|&s| BnString::new(s)).collect(); + let choices: Vec = choices.iter().map(BnString::new).collect(); let mut result = unsafe { std::mem::zeroed::() }; result.type_ = BNFormInputFieldType::ChoiceFormField; - result.prompt = prompt.as_ref().as_ptr() as *const c_char; - let mut raw_choices: Vec<*const c_char> = choices - .iter() - .map(|c| c.as_ref().as_ptr() as *const c_char) - .collect(); + result.prompt = prompt.as_ptr(); + let mut raw_choices: Vec<_> = choices.iter().map(|c| c.as_ptr()).collect(); result.choices = raw_choices.as_mut_ptr(); result.count = choices.len(); result.hasDefault = default.is_some(); @@ -350,20 +347,16 @@ impl FormInputBuilder { default: Option<&str>, ) -> Self { let prompt = BnString::new(prompt); - let ext = if let Some(ext) = ext { - BnString::new(ext) - } else { - BnString::new("") - }; + let ext = BnString::new(ext.unwrap_or_default()); let default = default.map(BnString::new); let mut result = unsafe { std::mem::zeroed::() }; result.type_ = BNFormInputFieldType::OpenFileNameFormField; - result.prompt = prompt.as_ref().as_ptr() as *const c_char; - result.ext = ext.as_ref().as_ptr() as *const c_char; + result.prompt = prompt.as_ptr(); + result.ext = ext.as_ptr(); result.hasDefault = default.is_some(); if let Some(ref default) = default { - result.stringDefault = default.as_ref().as_ptr() as *const c_char; + result.stringDefault = default.as_ptr(); } self.fields.push(result); @@ -384,26 +377,18 @@ impl FormInputBuilder { default: Option<&str>, ) -> Self { let prompt = BnString::new(prompt); - let ext = if let Some(ext) = ext { - BnString::new(ext) - } else { - BnString::new("") - }; - let default_name = if let Some(default_name) = default_name { - BnString::new(default_name) - } else { - BnString::new("") - }; + let ext = BnString::new(ext.unwrap_or_default()); + let default_name = BnString::new(default_name.unwrap_or_default()); let default = default.map(BnString::new); let mut result = unsafe { std::mem::zeroed::() }; result.type_ = BNFormInputFieldType::SaveFileNameFormField; - result.prompt = prompt.as_ref().as_ptr() as *const c_char; - result.ext = ext.as_ref().as_ptr() as *const c_char; - result.defaultName = default_name.as_ref().as_ptr() as *const c_char; + result.prompt = prompt.as_ptr(); + result.ext = ext.as_ptr(); + result.defaultName = default_name.as_ptr(); result.hasDefault = default.is_some(); if let Some(ref default) = default { - result.stringDefault = default.as_ref().as_ptr() as *const c_char; + result.stringDefault = default.as_ptr(); } self.fields.push(result); @@ -424,20 +409,16 @@ impl FormInputBuilder { default: Option<&str>, ) -> Self { let prompt = BnString::new(prompt); - let default_name = if let Some(default_name) = default_name { - BnString::new(default_name) - } else { - BnString::new("") - }; + let default_name = BnString::new(default_name.unwrap_or_default()); let default = default.map(BnString::new); let mut result = unsafe { std::mem::zeroed::() }; result.type_ = BNFormInputFieldType::DirectoryNameFormField; - result.prompt = prompt.as_ref().as_ptr() as *const c_char; - result.defaultName = default_name.as_ref().as_ptr() as *const c_char; + result.prompt = prompt.as_ptr(); + result.defaultName = default_name.as_ptr(); result.hasDefault = default.is_some(); if let Some(ref default) = default { - result.stringDefault = default.as_ref().as_ptr() as *const c_char; + result.stringDefault = default.as_ptr(); } self.fields.push(result); @@ -495,7 +476,7 @@ impl FormInputBuilder { BNGetFormInput( self.fields.as_mut_ptr(), self.fields.len(), - title.into_bytes_with_nul().as_ptr() as *const _, + title.as_cstr().as_ptr(), ) } { let result = self @@ -577,7 +558,7 @@ pub fn run_progress_dialog Result<(), ()>>)>( if unsafe { BNRunProgressDialog( - title.into_bytes_with_nul().as_ptr() as *mut _, + title.as_cstr().as_ptr(), can_cancel, Some(cb_task::), &mut ctxt as *mut _ as *mut c_void, diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 9499fd512..3ca9d18a2 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -110,7 +110,7 @@ use rc::Ref; use std::collections::HashMap; use std::ffi::{c_char, c_void, CStr}; use std::path::{Path, PathBuf}; -use string::BnStrCompatible; +use string::AsCStr; use string::BnString; use string::IntoJson; @@ -132,15 +132,13 @@ pub fn load_with_progress( file_path: impl AsRef, progress: impl Into, ) -> Option> { - let file_path = file_path.as_ref().into_bytes_with_nul(); - let options = c""; let boxed_progress = Box::new(progress.into()); let leaked_boxed_progress = Box::into_raw(boxed_progress); let handle = unsafe { BNLoadFilename( - file_path.as_ptr() as *mut _, + file_path.as_ref().as_cstr().as_ptr(), true, - options.as_ptr() as *mut c_char, + c"".as_ptr(), Some(ProgressExecutor::cb_execute), leaked_boxed_progress as *mut c_void, ) @@ -195,27 +193,20 @@ pub fn load_with_options_and_progress( where O: IntoJson, { - let file_path = file_path.as_ref().into_bytes_with_nul(); let options_or_default = if let Some(opt) = options { - opt.get_json_string() - .ok()? - .into_bytes_with_nul() - .as_ref() - .to_vec() + BnString::new(opt.get_json_string().ok()?) } else { Metadata::new_of_type(MetadataType::KeyValueDataType) .get_json_string() .ok()? - .as_ref() - .to_vec() }; let boxed_progress = Box::new(progress.into()); let leaked_boxed_progress = Box::into_raw(boxed_progress); let handle = unsafe { BNLoadFilename( - file_path.as_ptr() as *mut _, + file_path.as_ref().as_cstr().as_ptr(), update_analysis_and_wait, - options_or_default.as_ptr() as *mut c_char, + options_or_default.as_ptr(), Some(ProgressExecutor::cb_execute), leaked_boxed_progress as *mut c_void, ) @@ -255,17 +246,11 @@ where O: IntoJson, { let options_or_default = if let Some(opt) = options { - opt.get_json_string() - .ok()? - .into_bytes_with_nul() - .as_ref() - .to_vec() + BnString::new(opt.get_json_string().ok()?) } else { Metadata::new_of_type(MetadataType::KeyValueDataType) .get_json_string() .ok()? - .as_ref() - .to_vec() }; let boxed_progress = Box::new(progress.into()); let leaked_boxed_progress = Box::into_raw(boxed_progress); @@ -273,7 +258,7 @@ where BNLoadBinaryView( bv.handle as *mut _, update_analysis_and_wait, - options_or_default.as_ptr() as *mut c_char, + options_or_default.as_ptr(), Some(ProgressExecutor::cb_execute), leaked_boxed_progress as *mut c_void, ) @@ -303,8 +288,7 @@ pub fn bundled_plugin_directory() -> Result { } pub fn set_bundled_plugin_directory(new_dir: impl AsRef) { - let new_dir = new_dir.as_ref().into_bytes_with_nul(); - unsafe { BNSetBundledPluginDirectory(new_dir.as_ptr() as *const c_char) }; + unsafe { BNSetBundledPluginDirectory(new_dir.as_ref().as_cstr().as_ptr()) }; } pub fn user_directory() -> PathBuf { @@ -345,9 +329,7 @@ pub fn save_last_run() { } pub fn path_relative_to_bundled_plugin_directory(path: impl AsRef) -> Result { - let path_raw = path.as_ref().into_bytes_with_nul(); - let s: *mut c_char = - unsafe { BNGetPathRelativeToBundledPluginDirectory(path_raw.as_ptr() as *const c_char) }; + let s = unsafe { BNGetPathRelativeToBundledPluginDirectory(path.as_ref().as_cstr().as_ptr()) }; if s.is_null() { return Err(()); } @@ -355,9 +337,7 @@ pub fn path_relative_to_bundled_plugin_directory(path: impl AsRef) -> Resu } pub fn path_relative_to_user_plugin_directory(path: impl AsRef) -> Result { - let path_raw = path.as_ref().into_bytes_with_nul(); - let s: *mut c_char = - unsafe { BNGetPathRelativeToUserPluginDirectory(path_raw.as_ptr() as *const c_char) }; + let s = unsafe { BNGetPathRelativeToUserPluginDirectory(path.as_ref().as_cstr().as_ptr()) }; if s.is_null() { return Err(()); } @@ -365,9 +345,7 @@ pub fn path_relative_to_user_plugin_directory(path: impl AsRef) -> Result< } pub fn path_relative_to_user_directory(path: impl AsRef) -> Result { - let path_raw = path.as_ref().into_bytes_with_nul(); - let s: *mut c_char = - unsafe { BNGetPathRelativeToUserDirectory(path_raw.as_ptr() as *const c_char) }; + let s = unsafe { BNGetPathRelativeToUserDirectory(path.as_ref().as_cstr().as_ptr()) }; if s.is_null() { return Err(()); } @@ -501,10 +479,8 @@ pub fn license_count() -> i32 { /// If not set the normal license retrieval will occur: /// 1. Check the BN_LICENSE environment variable /// 2. Check the Binary Ninja user directory for license.dat -pub fn set_license(license: Option) { - let license = license.unwrap_or_default().into_bytes_with_nul(); - let license_slice = license.as_ref(); - unsafe { BNSetLicense(license_slice.as_ptr() as *const c_char) } +pub fn set_license(license: Option) { + unsafe { BNSetLicense(license.unwrap_or_default().as_cstr().as_ptr()) } } pub fn product() -> BnString { @@ -524,10 +500,8 @@ pub fn is_ui_enabled() -> bool { unsafe { BNIsUIEnabled() } } -pub fn is_database(filename: S) -> bool { - let filename = filename.into_bytes_with_nul(); - let filename_slice = filename.as_ref(); - unsafe { BNIsDatabase(filename_slice.as_ptr() as *const c_char) } +pub fn is_database(filename: S) -> bool { + unsafe { BNIsDatabase(filename.as_cstr().as_ptr()) } } pub fn plugin_abi_version() -> u32 { @@ -554,16 +528,12 @@ pub fn plugin_ui_abi_minimum_version() -> u32 { BN_MINIMUM_UI_ABI_VERSION } -pub fn add_required_plugin_dependency(name: S) { - unsafe { - BNAddRequiredPluginDependency(name.into_bytes_with_nul().as_ref().as_ptr() as *const c_char) - }; +pub fn add_required_plugin_dependency(name: S) { + unsafe { BNAddRequiredPluginDependency(name.as_cstr().as_ptr()) }; } -pub fn add_optional_plugin_dependency(name: S) { - unsafe { - BNAddOptionalPluginDependency(name.into_bytes_with_nul().as_ref().as_ptr() as *const c_char) - }; +pub fn add_optional_plugin_dependency(name: S) { + unsafe { BNAddOptionalPluginDependency(name.as_cstr().as_ptr()) }; } // Provide ABI version automatically so that the core can verify binary compatibility diff --git a/rust/src/medium_level_il/function.rs b/rust/src/medium_level_il/function.rs index c7a53b601..62e095eda 100644 --- a/rust/src/medium_level_il/function.rs +++ b/rust/src/medium_level_il/function.rs @@ -1,5 +1,4 @@ use binaryninjacore_sys::*; -use std::ffi::c_char; use std::fmt::{Debug, Formatter}; use std::hash::{Hash, Hasher}; @@ -11,7 +10,7 @@ use crate::disassembly::DisassemblySettings; use crate::flowgraph::FlowGraph; use crate::function::{Function, Location}; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref, RefCountable}; -use crate::string::BnStrCompatible; +use crate::string::AsCStr; use crate::types::Type; use crate::variable::{PossibleValueSet, RegisterValue, SSAVariable, UserVariableValue, Variable}; @@ -119,20 +118,19 @@ impl MediumLevelILFunction { unsafe { Array::new(raw_instr_idxs, count, self.to_owned()) } } - pub fn create_user_stack_var<'a, S: BnStrCompatible, C: Into>>( + pub fn create_user_stack_var<'a, S: AsCStr, C: Into>>( self, offset: i64, var_type: C, name: S, ) { let mut owned_raw_var_ty = Conf::<&Type>::into_raw(var_type.into()); - let name = name.into_bytes_with_nul(); unsafe { BNCreateUserStackVariable( self.function().handle, offset, &mut owned_raw_var_ty, - name.as_ref().as_ptr() as *const c_char, + name.as_cstr().as_ptr(), ) } } @@ -141,7 +139,7 @@ impl MediumLevelILFunction { unsafe { BNDeleteUserStackVariable(self.function().handle, offset) } } - pub fn create_user_var<'a, S: BnStrCompatible, C: Into>>( + pub fn create_user_var<'a, S: AsCStr, C: Into>>( &self, var: &Variable, var_type: C, @@ -150,13 +148,12 @@ impl MediumLevelILFunction { ) { let raw_var = BNVariable::from(var); let mut owned_raw_var_ty = Conf::<&Type>::into_raw(var_type.into()); - let name = name.into_bytes_with_nul(); unsafe { BNCreateUserVariable( self.function().handle, &raw_var, &mut owned_raw_var_ty, - name.as_ref().as_ptr() as *const _, + name.as_cstr().as_ptr(), ignore_disjoint_uses, ) } @@ -266,21 +263,19 @@ impl MediumLevelILFunction { Ok(()) } - pub fn create_auto_stack_var<'a, T: Into>, S: BnStrCompatible>( + pub fn create_auto_stack_var<'a, T: Into>, S: AsCStr>( &self, offset: i64, var_type: T, name: S, ) { let mut owned_raw_var_ty = Conf::<&Type>::into_raw(var_type.into()); - let name = name.into_bytes_with_nul(); - let name_c_str = name.as_ref(); unsafe { BNCreateAutoStackVariable( self.function().handle, offset, &mut owned_raw_var_ty, - name_c_str.as_ptr() as *const c_char, + name.as_cstr().as_ptr(), ) } } @@ -289,7 +284,7 @@ impl MediumLevelILFunction { unsafe { BNDeleteAutoStackVariable(self.function().handle, offset) } } - pub fn create_auto_var<'a, S: BnStrCompatible, C: Into>>( + pub fn create_auto_var<'a, S: AsCStr, C: Into>>( &self, var: &Variable, var_type: C, @@ -298,14 +293,12 @@ impl MediumLevelILFunction { ) { let raw_var = BNVariable::from(var); let mut owned_raw_var_ty = Conf::<&Type>::into_raw(var_type.into()); - let name = name.into_bytes_with_nul(); - let name_c_str = name.as_ref(); unsafe { BNCreateAutoVariable( self.function().handle, &raw_var, &mut owned_raw_var_ty, - name_c_str.as_ptr() as *const c_char, + name.as_cstr().as_ptr(), ignore_disjoint_uses, ) } diff --git a/rust/src/metadata.rs b/rust/src/metadata.rs index d18b63395..2646e413a 100644 --- a/rust/src/metadata.rs +++ b/rust/src/metadata.rs @@ -1,5 +1,5 @@ use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString, IntoJson}; +use crate::string::{AsCStr, BnString, IntoJson}; use binaryninjacore_sys::*; use std::collections::HashMap; use std::os::raw::c_char; @@ -265,16 +265,12 @@ impl Metadata { Ok(Some(unsafe { Self::ref_from_raw(ptr) })) } - pub fn get(&self, key: S) -> Result>, ()> { + pub fn get(&self, key: S) -> Result>, ()> { if self.get_type() != MetadataType::KeyValueDataType { return Err(()); } - let ptr: *mut BNMetadata = unsafe { - BNMetadataGetForKey( - self.handle, - key.into_bytes_with_nul().as_ref().as_ptr() as *const c_char, - ) - }; + let ptr: *mut BNMetadata = + unsafe { BNMetadataGetForKey(self.handle, key.as_cstr().as_ptr()) }; if ptr.is_null() { return Ok(None); } @@ -289,18 +285,12 @@ impl Metadata { Ok(()) } - pub fn insert(&self, key: S, value: &Metadata) -> Result<(), ()> { + pub fn insert(&self, key: S, value: &Metadata) -> Result<(), ()> { if self.get_type() != MetadataType::KeyValueDataType { return Err(()); } - unsafe { - BNMetadataSetValueForKey( - self.handle, - key.into_bytes_with_nul().as_ref().as_ptr() as *const c_char, - value.handle, - ) - }; + unsafe { BNMetadataSetValueForKey(self.handle, key.as_cstr().as_ptr(), value.handle) }; Ok(()) } @@ -313,17 +303,12 @@ impl Metadata { Ok(()) } - pub fn remove_key(&self, key: S) -> Result<(), ()> { + pub fn remove_key(&self, key: S) -> Result<(), ()> { if self.get_type() != MetadataType::KeyValueDataType { return Err(()); } - unsafe { - BNMetadataRemoveKey( - self.handle, - key.into_bytes_with_nul().as_ref().as_ptr() as *const c_char, - ) - }; + unsafe { BNMetadataRemoveKey(self.handle, key.as_cstr().as_ptr()) }; Ok(()) } } @@ -394,21 +379,13 @@ impl From for Ref { impl From for Ref { fn from(value: String) -> Self { - unsafe { - Metadata::ref_from_raw(BNCreateMetadataStringData( - value.into_bytes_with_nul().as_ptr() as *const c_char, - )) - } + unsafe { Metadata::ref_from_raw(BNCreateMetadataStringData(value.as_cstr().as_ptr())) } } } impl From<&str> for Ref { fn from(value: &str) -> Self { - unsafe { - Metadata::ref_from_raw(BNCreateMetadataStringData( - value.into_bytes_with_nul().as_ptr() as *const c_char, - )) - } + unsafe { Metadata::ref_from_raw(BNCreateMetadataStringData(value.as_cstr().as_ptr())) } } } @@ -442,17 +419,14 @@ impl From<&Array> for Ref { } } -impl From>> for Ref { +impl From>> for Ref { fn from(value: HashMap>) -> Self { - let data: Vec<(S::Result, Ref)> = value - .into_iter() - .map(|(k, v)| (k.into_bytes_with_nul(), v)) - .collect(); - let mut keys: Vec<*const c_char> = data + let data = value .iter() - .map(|(k, _)| k.as_ref().as_ptr() as *const c_char) - .collect(); - let mut values: Vec<*mut BNMetadata> = data.iter().map(|(_, v)| v.handle).collect(); + .map(|(k, v)| (k.as_cstr(), v)) + .collect::>(); + let mut keys = data.iter().map(|(k, _)| k.as_ptr()).collect::>(); + let mut values = data.iter().map(|(_, v)| v.handle).collect::>(); unsafe { Metadata::ref_from_raw(BNCreateMetadataValueStore( @@ -466,19 +440,16 @@ impl From>> for Ref { impl From<&[(S, T)]> for Ref where - S: BnStrCompatible + Copy, + S: AsCStr, for<'a> &'a T: Into>, { fn from(value: &[(S, T)]) -> Self { - let data: Vec<(S::Result, Ref)> = value - .iter() - .map(|(k, v)| (k.into_bytes_with_nul(), v.into())) - .collect(); - let mut keys: Vec<*const c_char> = data + let data = value .iter() - .map(|(k, _)| k.as_ref().as_ptr() as *const c_char) - .collect(); - let mut values: Vec<*mut BNMetadata> = data.iter().map(|(_, v)| v.handle).collect(); + .map(|(k, v)| (k.as_cstr(), v.into())) + .collect::>(); + let mut keys = data.iter().map(|(k, _)| k.as_ptr()).collect::>(); + let mut values = data.iter().map(|(_, v)| v.handle).collect::>(); unsafe { Metadata::ref_from_raw(BNCreateMetadataValueStore( @@ -492,7 +463,7 @@ where impl From<[(S, T); N]> for Ref where - S: BnStrCompatible + Copy, + S: AsCStr, for<'a> &'a T: Into>, { fn from(value: [(S, T); N]) -> Self { @@ -546,19 +517,13 @@ impl From<&Vec> for Ref { } } -impl From> for Ref { +impl From> for Ref { fn from(value: Vec) -> Self { - let mut refs = vec![]; - for v in value { - refs.push(v.into_bytes_with_nul()); - } - let mut pointers = vec![]; - for r in &refs { - pointers.push(r.as_ref().as_ptr() as *const c_char); - } + let refs = value.iter().map(|v| v.as_cstr()).collect::>(); + let mut pointers = refs.iter().map(|r| r.as_ptr()).collect::>(); unsafe { Metadata::ref_from_raw(BNCreateMetadataStringListData( - pointers.as_ptr() as *mut *const c_char, + pointers.as_mut_ptr(), pointers.len(), )) } diff --git a/rust/src/platform.rs b/rust/src/platform.rs index f8f00a968..114b9f504 100644 --- a/rust/src/platform.rs +++ b/rust/src/platform.rs @@ -79,10 +79,9 @@ impl Platform { Ref::new(Self { handle }) } - pub fn by_name(name: S) -> Option> { - let raw_name = name.into_bytes_with_nul(); + pub fn by_name(name: S) -> Option> { unsafe { - let res = BNGetPlatformByName(raw_name.as_ref().as_ptr() as *mut _); + let res = BNGetPlatformByName(name.as_cstr().as_ptr()); if res.is_null() { None @@ -110,27 +109,20 @@ impl Platform { } } - pub fn list_by_os(name: S) -> Array { - let raw_name = name.into_bytes_with_nul(); - + pub fn list_by_os(name: S) -> Array { unsafe { let mut count = 0; - let handles = BNGetPlatformListByOS(raw_name.as_ref().as_ptr() as *mut _, &mut count); + let handles = BNGetPlatformListByOS(name.as_cstr().as_ptr(), &mut count); Array::new(handles, count, ()) } } - pub fn list_by_os_and_arch( - name: S, - arch: &CoreArchitecture, - ) -> Array { - let raw_name = name.into_bytes_with_nul(); - + pub fn list_by_os_and_arch(name: S, arch: &CoreArchitecture) -> Array { unsafe { let mut count = 0; let handles = BNGetPlatformListByOSAndArchitecture( - raw_name.as_ref().as_ptr() as *mut _, + name.as_cstr().as_ptr(), arch.handle, &mut count, ); @@ -148,10 +140,9 @@ impl Platform { } } - pub fn new(arch: &A, name: S) -> Ref { - let name = name.into_bytes_with_nul(); + pub fn new(arch: &A, name: S) -> Ref { unsafe { - let handle = BNCreatePlatform(arch.as_ref().handle, name.as_ref().as_ptr() as *mut _); + let handle = BNCreatePlatform(arch.as_ref().handle, name.as_cstr().as_ptr()); assert!(!handle.is_null()); Ref::new(Self { handle }) } @@ -176,25 +167,18 @@ impl Platform { unsafe { TypeContainer::from_raw(type_container_ptr.unwrap()).clone() } } - pub fn get_type_libraries_by_name(&self, name: T) -> Array { + pub fn get_type_libraries_by_name(&self, name: T) -> Array { let mut count = 0; - let name = name.into_bytes_with_nul(); let result = unsafe { - BNGetPlatformTypeLibrariesByName( - self.handle, - name.as_ref().as_ptr() as *mut _, - &mut count, - ) + BNGetPlatformTypeLibrariesByName(self.handle, name.as_cstr().as_ptr(), &mut count) }; assert!(!result.is_null()); unsafe { Array::new(result, count, ()) } } - pub fn register_os(&self, os: S) { - let os = os.into_bytes_with_nul(); - + pub fn register_os(&self, os: S) { unsafe { - BNRegisterPlatform(os.as_ref().as_ptr() as *mut _, self.handle); + BNRegisterPlatform(os.as_cstr().as_ptr(), self.handle); } } @@ -275,15 +259,12 @@ impl Platform { file_name: &str, include_dirs: &[BnString], ) -> Result { - let source_cstr = BnString::new(source); - let file_name_cstr = BnString::new(file_name); - let mut result = ptr::null_mut(); let mut error_string = ptr::null_mut(); let success = unsafe { BNPreprocessSource( - source_cstr.as_ptr(), - file_name_cstr.as_ptr(), + source.as_cstr().as_ptr(), + file_name.as_cstr().as_ptr(), &mut result, &mut error_string, include_dirs.as_ptr() as *mut *const ffi::c_char, @@ -314,22 +295,18 @@ impl Platform { include_dirs: &[BnString], auto_type_source: &str, ) -> Result { - let source_cstr = BnString::new(src); - let file_name_cstr = BnString::new(filename); - let auto_type_source = BnString::new(auto_type_source); - let mut raw_result = BNTypeParserResult::default(); let mut error_string = ptr::null_mut(); let success = unsafe { BNParseTypesFromSource( self.handle, - source_cstr.as_ptr(), - file_name_cstr.as_ptr(), + src.as_cstr().as_ptr(), + filename.as_cstr().as_ptr(), &mut raw_result, &mut error_string, include_dirs.as_ptr() as *mut *const ffi::c_char, include_dirs.len(), - auto_type_source.as_ptr(), + auto_type_source.as_cstr().as_ptr(), ) }; @@ -357,20 +334,17 @@ impl Platform { include_dirs: &[BnString], auto_type_source: &str, ) -> Result { - let file_name_cstr = BnString::new(filename); - let auto_type_source = BnString::new(auto_type_source); - let mut raw_result = BNTypeParserResult::default(); let mut error_string = ptr::null_mut(); let success = unsafe { BNParseTypesFromSourceFile( self.handle, - file_name_cstr.as_ptr(), + filename.as_cstr().as_ptr(), &mut raw_result, &mut error_string, include_dirs.as_ptr() as *mut *const ffi::c_char, include_dirs.len(), - auto_type_source.as_ptr(), + auto_type_source.as_cstr().as_ptr(), ) }; diff --git a/rust/src/project.rs b/rust/src/project.rs index 8d8132cac..720593333 100644 --- a/rust/src/project.rs +++ b/rust/src/project.rs @@ -1,7 +1,7 @@ pub mod file; pub mod folder; -use std::ffi::{c_char, c_void}; +use std::ffi::c_void; use std::fmt::Debug; use std::ptr::{null_mut, NonNull}; use std::time::{Duration, SystemTime, UNIX_EPOCH}; @@ -13,7 +13,7 @@ use crate::progress::ProgressExecutor; use crate::project::file::ProjectFile; use crate::project::folder::ProjectFolder; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; pub struct Project { handle: NonNull, @@ -39,24 +39,16 @@ impl Project { /// /// * `path` - Path to the project directory (.bnpr) /// * `name` - Name of the new project - pub fn create(path: P, name: S) -> Option> { - let path_raw = path.into_bytes_with_nul(); - let name_raw = name.into_bytes_with_nul(); - let handle = unsafe { - BNCreateProject( - path_raw.as_ref().as_ptr() as *const c_char, - name_raw.as_ref().as_ptr() as *const c_char, - ) - }; + pub fn create(path: P, name: S) -> Option> { + let handle = unsafe { BNCreateProject(path.as_cstr().as_ptr(), name.as_cstr().as_ptr()) }; NonNull::new(handle).map(|h| unsafe { Self::ref_from_raw(h) }) } /// Open an existing project /// /// * `path` - Path to the project directory (.bnpr) or project metadata file (.bnpm) - pub fn open_project(path: P) -> Option> { - let path_raw = path.into_bytes_with_nul(); - let handle = unsafe { BNOpenProject(path_raw.as_ref().as_ptr() as *const c_char) }; + pub fn open_project(path: P) -> Option> { + let handle = unsafe { BNOpenProject(path.as_cstr().as_ptr()) }; NonNull::new(handle).map(|h| unsafe { Self::ref_from_raw(h) }) } @@ -99,14 +91,8 @@ impl Project { } /// Set the name of the project - pub fn set_name(&self, value: S) { - let value = value.into_bytes_with_nul(); - unsafe { - BNProjectSetName( - self.handle.as_ptr(), - value.as_ref().as_ptr() as *const c_char, - ) - } + pub fn set_name(&self, value: S) { + unsafe { BNProjectSetName(self.handle.as_ptr(), value.as_cstr().as_ptr()) } } /// Get the description of the project @@ -115,22 +101,14 @@ impl Project { } /// Set the description of the project - pub fn set_description(&self, value: S) { - let value = value.into_bytes_with_nul(); - unsafe { - BNProjectSetDescription( - self.handle.as_ptr(), - value.as_ref().as_ptr() as *const c_char, - ) - } + pub fn set_description(&self, value: S) { + unsafe { BNProjectSetDescription(self.handle.as_ptr(), value.as_cstr().as_ptr()) } } /// Retrieves metadata stored under a key from the project - pub fn query_metadata(&self, key: S) -> Ref { - let key = key.into_bytes_with_nul(); - let result = unsafe { - BNProjectQueryMetadata(self.handle.as_ptr(), key.as_ref().as_ptr() as *const c_char) - }; + pub fn query_metadata(&self, key: S) -> Ref { + let result = + unsafe { BNProjectQueryMetadata(self.handle.as_ptr(), key.as_cstr().as_ptr()) }; unsafe { Metadata::ref_from_raw(result) } } @@ -138,26 +116,15 @@ impl Project { /// /// * `key` - Key under which to store the Metadata object /// * `value` - Object to store - pub fn store_metadata(&self, key: S, value: &Metadata) -> bool { - let key_raw = key.into_bytes_with_nul(); + pub fn store_metadata(&self, key: S, value: &Metadata) -> bool { unsafe { - BNProjectStoreMetadata( - self.handle.as_ptr(), - key_raw.as_ref().as_ptr() as *const c_char, - value.handle, - ) + BNProjectStoreMetadata(self.handle.as_ptr(), key.as_cstr().as_ptr(), value.handle) } } /// Removes the metadata associated with this `key` from the project - pub fn remove_metadata(&self, key: S) { - let key_raw = key.into_bytes_with_nul(); - unsafe { - BNProjectRemoveMetadata( - self.handle.as_ptr(), - key_raw.as_ref().as_ptr() as *const c_char, - ) - } + pub fn remove_metadata(&self, key: S) { + unsafe { BNProjectRemoveMetadata(self.handle.as_ptr(), key.as_cstr().as_ptr()) } } pub fn push_folder(&self, file: &ProjectFolder) { @@ -176,8 +143,8 @@ impl Project { description: D, ) -> Result, ()> where - P: BnStrCompatible, - D: BnStrCompatible, + P: AsCStr, + D: AsCStr, { self.create_folder_from_path_with_progress( path, @@ -201,20 +168,18 @@ impl Project { progress: impl Into, ) -> Result, ()> where - P: BnStrCompatible, - D: BnStrCompatible, + P: AsCStr, + D: AsCStr, { - let path_raw = path.into_bytes_with_nul(); - let description_raw = description.into_bytes_with_nul(); let parent_ptr = parent.map(|p| p.handle.as_ptr()).unwrap_or(null_mut()); let boxed_progress = Box::new(progress.into()); let leaked_boxed_progress = Box::into_raw(boxed_progress); unsafe { let result = BNProjectCreateFolderFromPath( self.handle.as_ptr(), - path_raw.as_ref().as_ptr() as *const c_char, + path.as_cstr().as_ptr(), parent_ptr, - description_raw.as_ref().as_ptr() as *const c_char, + description.as_cstr().as_ptr(), leaked_boxed_progress as *mut c_void, Some(ProgressExecutor::cb_execute), ); @@ -235,18 +200,16 @@ impl Project { description: D, ) -> Result, ()> where - N: BnStrCompatible, - D: BnStrCompatible, + N: AsCStr, + D: AsCStr, { - let name_raw = name.into_bytes_with_nul(); - let description_raw = description.into_bytes_with_nul(); let parent_ptr = parent.map(|p| p.handle.as_ptr()).unwrap_or(null_mut()); unsafe { let result = BNProjectCreateFolder( self.handle.as_ptr(), parent_ptr, - name_raw.as_ref().as_ptr() as *const c_char, - description_raw.as_ref().as_ptr() as *const c_char, + name.as_cstr().as_ptr(), + description.as_cstr().as_ptr(), ); Ok(ProjectFolder::ref_from_raw(NonNull::new(result).ok_or(())?)) } @@ -266,21 +229,18 @@ impl Project { id: I, ) -> Result, ()> where - N: BnStrCompatible, - D: BnStrCompatible, - I: BnStrCompatible, + N: AsCStr, + D: AsCStr, + I: AsCStr, { - let name_raw = name.into_bytes_with_nul(); - let description_raw = description.into_bytes_with_nul(); let parent_ptr = parent.map(|p| p.handle.as_ptr()).unwrap_or(null_mut()); - let id_raw = id.into_bytes_with_nul(); unsafe { let result = BNProjectCreateFolderUnsafe( self.handle.as_ptr(), parent_ptr, - name_raw.as_ref().as_ptr() as *const c_char, - description_raw.as_ref().as_ptr() as *const c_char, - id_raw.as_ref().as_ptr() as *const c_char, + name.as_cstr().as_ptr(), + description.as_cstr().as_ptr(), + id.as_cstr().as_ptr(), ); Ok(ProjectFolder::ref_from_raw(NonNull::new(result).ok_or(())?)) } @@ -298,10 +258,8 @@ impl Project { } /// Retrieve a folder in the project by unique folder `id` - pub fn folder_by_id(&self, id: S) -> Option> { - let id_raw = id.into_bytes_with_nul(); - let id_ptr = id_raw.as_ref().as_ptr() as *const c_char; - let result = unsafe { BNProjectGetFolderById(self.handle.as_ptr(), id_ptr) }; + pub fn folder_by_id(&self, id: S) -> Option> { + let result = unsafe { BNProjectGetFolderById(self.handle.as_ptr(), id.as_cstr().as_ptr()) }; let handle = NonNull::new(result)?; Some(unsafe { ProjectFolder::ref_from_raw(handle) }) } @@ -358,9 +316,9 @@ impl Project { description: D, ) -> Result, ()> where - P: BnStrCompatible, - N: BnStrCompatible, - D: BnStrCompatible, + P: AsCStr, + N: AsCStr, + D: AsCStr, { self.create_file_from_path_with_progress( path, @@ -387,23 +345,20 @@ impl Project { progress: impl Into, ) -> Result, ()> where - P: BnStrCompatible, - N: BnStrCompatible, - D: BnStrCompatible, + P: AsCStr, + N: AsCStr, + D: AsCStr, { - let path_raw = path.into_bytes_with_nul(); - let name_raw = name.into_bytes_with_nul(); - let description_raw = description.into_bytes_with_nul(); let folder_ptr = folder.map(|p| p.handle.as_ptr()).unwrap_or(null_mut()); let boxed_progress = Box::new(progress.into()); let leaked_boxed_progress = Box::into_raw(boxed_progress); unsafe { let result = BNProjectCreateFileFromPath( self.handle.as_ptr(), - path_raw.as_ref().as_ptr() as *const c_char, + path.as_cstr().as_ptr(), folder_ptr, - name_raw.as_ref().as_ptr() as *const c_char, - description_raw.as_ref().as_ptr() as *const c_char, + name.as_cstr().as_ptr(), + description.as_cstr().as_ptr(), leaked_boxed_progress as *mut c_void, Some(ProgressExecutor::cb_execute), ); @@ -430,10 +385,10 @@ impl Project { creation_time: SystemTime, ) -> Result, ()> where - P: BnStrCompatible, - N: BnStrCompatible, - D: BnStrCompatible, - I: BnStrCompatible, + P: AsCStr, + N: AsCStr, + D: AsCStr, + I: AsCStr, { self.create_file_from_path_unsafe_with_progress( path, @@ -467,26 +422,22 @@ impl Project { progress: impl Into, ) -> Result, ()> where - P: BnStrCompatible, - N: BnStrCompatible, - D: BnStrCompatible, - I: BnStrCompatible, + P: AsCStr, + N: AsCStr, + D: AsCStr, + I: AsCStr, { - let path_raw = path.into_bytes_with_nul(); - let name_raw = name.into_bytes_with_nul(); - let description_raw = description.into_bytes_with_nul(); - let id_raw = id.into_bytes_with_nul(); let folder_ptr = folder.map(|p| p.handle.as_ptr()).unwrap_or(null_mut()); let boxed_progress = Box::new(progress.into()); let leaked_boxed_progress = Box::into_raw(boxed_progress); unsafe { let result = BNProjectCreateFileFromPathUnsafe( self.handle.as_ptr(), - path_raw.as_ref().as_ptr() as *const c_char, + path.as_cstr().as_ptr(), folder_ptr, - name_raw.as_ref().as_ptr() as *const c_char, - description_raw.as_ref().as_ptr() as *const c_char, - id_raw.as_ref().as_ptr() as *const c_char, + name.as_cstr().as_ptr(), + description.as_cstr().as_ptr(), + id.as_cstr().as_ptr(), systime_to_bntime(creation_time).unwrap(), leaked_boxed_progress as *mut c_void, Some(ProgressExecutor::cb_execute), @@ -510,8 +461,8 @@ impl Project { description: D, ) -> Result, ()> where - N: BnStrCompatible, - D: BnStrCompatible, + N: AsCStr, + D: AsCStr, { self.create_file_with_progress( contents, @@ -538,11 +489,9 @@ impl Project { progress: impl Into, ) -> Result, ()> where - N: BnStrCompatible, - D: BnStrCompatible, + N: AsCStr, + D: AsCStr, { - let name_raw = name.into_bytes_with_nul(); - let description_raw = description.into_bytes_with_nul(); let folder_ptr = folder.map(|p| p.handle.as_ptr()).unwrap_or(null_mut()); let boxed_progress = Box::new(progress.into()); let leaked_boxed_progress = Box::into_raw(boxed_progress); @@ -552,8 +501,8 @@ impl Project { contents.as_ptr(), contents.len(), folder_ptr, - name_raw.as_ref().as_ptr() as *const c_char, - description_raw.as_ref().as_ptr() as *const c_char, + name.as_cstr().as_ptr(), + description.as_cstr().as_ptr(), leaked_boxed_progress as *mut c_void, Some(ProgressExecutor::cb_execute), ); @@ -580,9 +529,9 @@ impl Project { creation_time: SystemTime, ) -> Result, ()> where - N: BnStrCompatible, - D: BnStrCompatible, - I: BnStrCompatible, + N: AsCStr, + D: AsCStr, + I: AsCStr, { self.create_file_unsafe_with_progress( contents, @@ -616,13 +565,10 @@ impl Project { progress: impl Into, ) -> Result, ()> where - N: BnStrCompatible, - D: BnStrCompatible, - I: BnStrCompatible, + N: AsCStr, + D: AsCStr, + I: AsCStr, { - let name_raw = name.into_bytes_with_nul(); - let description_raw = description.into_bytes_with_nul(); - let id_raw = id.into_bytes_with_nul(); let folder_ptr = folder.map(|p| p.handle.as_ptr()).unwrap_or(null_mut()); let boxed_progress = Box::new(progress.into()); let leaked_boxed_progress = Box::into_raw(boxed_progress); @@ -632,9 +578,9 @@ impl Project { contents.as_ptr(), contents.len(), folder_ptr, - name_raw.as_ref().as_ptr() as *const c_char, - description_raw.as_ref().as_ptr() as *const c_char, - id_raw.as_ref().as_ptr() as *const c_char, + name.as_cstr().as_ptr(), + description.as_cstr().as_ptr(), + id.as_cstr().as_ptr(), systime_to_bntime(creation_time).unwrap(), leaked_boxed_progress as *mut c_void, Some(ProgressExecutor::cb_execute), @@ -653,21 +599,16 @@ impl Project { } /// Retrieve a file in the project by unique `id` - pub fn file_by_id(&self, id: S) -> Option> { - let id_raw = id.into_bytes_with_nul(); - let id_ptr = id_raw.as_ref().as_ptr() as *const c_char; - - let result = unsafe { BNProjectGetFileById(self.handle.as_ptr(), id_ptr) }; + pub fn file_by_id(&self, id: S) -> Option> { + let result = unsafe { BNProjectGetFileById(self.handle.as_ptr(), id.as_cstr().as_ptr()) }; let handle = NonNull::new(result)?; Some(unsafe { ProjectFile::ref_from_raw(handle) }) } /// Retrieve a file in the project by the `path` on disk - pub fn file_by_path(&self, path: S) -> Option> { - let path_raw = path.into_bytes_with_nul(); - let path_ptr = path_raw.as_ref().as_ptr() as *const c_char; - - let result = unsafe { BNProjectGetFileByPathOnDisk(self.handle.as_ptr(), path_ptr) }; + pub fn file_by_path(&self, path: S) -> Option> { + let result = + unsafe { BNProjectGetFileByPathOnDisk(self.handle.as_ptr(), path.as_cstr().as_ptr()) }; let handle = NonNull::new(result)?; Some(unsafe { ProjectFile::ref_from_raw(handle) }) } diff --git a/rust/src/project/file.rs b/rust/src/project/file.rs index 5071dd50b..464c27c1e 100644 --- a/rust/src/project/file.rs +++ b/rust/src/project/file.rs @@ -1,6 +1,6 @@ use crate::project::{systime_from_bntime, Project, ProjectFolder}; use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; use binaryninjacore_sys::{ BNFreeProjectFile, BNFreeProjectFileList, BNNewProjectFileReference, BNProjectFile, BNProjectFileExistsOnDisk, BNProjectFileExport, BNProjectFileGetCreationTimestamp, @@ -8,7 +8,6 @@ use binaryninjacore_sys::{ BNProjectFileGetPathOnDisk, BNProjectFileGetProject, BNProjectFileSetDescription, BNProjectFileSetFolder, BNProjectFileSetName, }; -use std::ffi::c_char; use std::fmt::Debug; use std::ptr::{null_mut, NonNull}; use std::time::SystemTime; @@ -57,14 +56,8 @@ impl ProjectFile { } /// Set the name of this file - pub fn set_name(&self, value: S) -> bool { - let value_raw = value.into_bytes_with_nul(); - unsafe { - BNProjectFileSetName( - self.handle.as_ptr(), - value_raw.as_ref().as_ptr() as *const c_char, - ) - } + pub fn set_name(&self, value: S) -> bool { + unsafe { BNProjectFileSetName(self.handle.as_ptr(), value.as_cstr().as_ptr()) } } /// Get the description of this file @@ -73,14 +66,8 @@ impl ProjectFile { } /// Set the description of this file - pub fn set_description(&self, value: S) -> bool { - let value_raw = value.into_bytes_with_nul(); - unsafe { - BNProjectFileSetDescription( - self.handle.as_ptr(), - value_raw.as_ref().as_ptr() as *const c_char, - ) - } + pub fn set_description(&self, value: S) -> bool { + unsafe { BNProjectFileSetDescription(self.handle.as_ptr(), value.as_cstr().as_ptr()) } } /// Get the file creation time @@ -104,14 +91,8 @@ impl ProjectFile { /// Export this file to disk, `true' if the export succeeded /// /// * `dest` - Destination path for the exported contents - pub fn export(&self, dest: S) -> bool { - let dest_raw = dest.into_bytes_with_nul(); - unsafe { - BNProjectFileExport( - self.handle.as_ptr(), - dest_raw.as_ref().as_ptr() as *const c_char, - ) - } + pub fn export(&self, dest: S) -> bool { + unsafe { BNProjectFileExport(self.handle.as_ptr(), dest.as_cstr().as_ptr()) } } } diff --git a/rust/src/project/folder.rs b/rust/src/project/folder.rs index ea2789dd3..3c2026085 100644 --- a/rust/src/project/folder.rs +++ b/rust/src/project/folder.rs @@ -1,14 +1,14 @@ use crate::progress::ProgressExecutor; use crate::project::Project; use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; use binaryninjacore_sys::{ BNFreeProjectFolder, BNFreeProjectFolderList, BNNewProjectFolderReference, BNProjectFolder, BNProjectFolderExport, BNProjectFolderGetDescription, BNProjectFolderGetId, BNProjectFolderGetName, BNProjectFolderGetParent, BNProjectFolderGetProject, BNProjectFolderSetDescription, BNProjectFolderSetName, BNProjectFolderSetParent, }; -use std::ffi::{c_char, c_void}; +use std::ffi::c_void; use std::fmt::Debug; use std::ptr::{null_mut, NonNull}; @@ -46,14 +46,8 @@ impl ProjectFolder { } /// Set the name of this folder - pub fn set_name(&self, value: S) -> bool { - let value_raw = value.into_bytes_with_nul(); - unsafe { - BNProjectFolderSetName( - self.handle.as_ptr(), - value_raw.as_ref().as_ptr() as *const c_char, - ) - } + pub fn set_name(&self, value: S) -> bool { + unsafe { BNProjectFolderSetName(self.handle.as_ptr(), value.as_cstr().as_ptr()) } } /// Get the description of this folder @@ -62,14 +56,8 @@ impl ProjectFolder { } /// Set the description of this folder - pub fn set_description(&self, value: S) -> bool { - let value_raw = value.into_bytes_with_nul(); - unsafe { - BNProjectFolderSetDescription( - self.handle.as_ptr(), - value_raw.as_ref().as_ptr() as *const c_char, - ) - } + pub fn set_description(&self, value: S) -> bool { + unsafe { BNProjectFolderSetDescription(self.handle.as_ptr(), value.as_cstr().as_ptr()) } } /// Get the folder that contains this folder @@ -88,7 +76,7 @@ impl ProjectFolder { /// Recursively export this folder to disk, returns `true' if the export succeeded /// /// * `dest` - Destination path for the exported contents - pub fn export(&self, dest: S) -> bool { + pub fn export(&self, dest: S) -> bool { self.export_with_progress(dest, ProgressExecutor::default()) } @@ -99,15 +87,14 @@ impl ProjectFolder { /// * `progress` - [`ProgressExecutor`] that will be called as contents are exporting pub fn export_with_progress(&self, dest: S, progress: impl Into) -> bool where - S: BnStrCompatible, + S: AsCStr, { - let dest_raw = dest.into_bytes_with_nul(); let boxed_progress = Box::new(progress.into()); let leaked_boxed_progress = Box::into_raw(boxed_progress); let success = unsafe { BNProjectFolderExport( self.handle.as_ptr(), - dest_raw.as_ref().as_ptr() as *const c_char, + dest.as_cstr().as_ptr(), leaked_boxed_progress as *mut c_void, Some(ProgressExecutor::cb_execute), ) diff --git a/rust/src/relocation.rs b/rust/src/relocation.rs index 8fa9a86b0..9e76e0686 100644 --- a/rust/src/relocation.rs +++ b/rust/src/relocation.rs @@ -1,6 +1,6 @@ use crate::low_level_il::RegularLowLevelILFunction; use crate::rc::Guard; -use crate::string::BnStrCompatible; +use crate::string::AsCStr; use crate::{ architecture::CoreArchitecture, binary_view::BinaryView, @@ -404,7 +404,7 @@ unsafe impl RefCountable for CoreRelocationHandler { pub(crate) fn register_relocation_handler(arch: &CoreArchitecture, name: S, func: F) where - S: BnStrCompatible, + S: AsCStr, R: 'static + RelocationHandler> + Send + Sync + Sized, F: FnOnce(CustomRelocationHandlerHandle, CoreRelocationHandler) -> R, { @@ -503,8 +503,6 @@ where .into() } - let name = name.into_bytes_with_nul(); - let raw = Box::leak(Box::new( MaybeUninit::>::zeroed(), )); @@ -529,7 +527,7 @@ where BNArchitectureRegisterRelocationHandler( arch.handle, - name.as_ref().as_ptr() as *const _, + name.as_cstr().as_ptr(), handle.handle().as_ref().0, ); } diff --git a/rust/src/section.rs b/rust/src/section.rs index 1a03ca36d..f34014ec9 100644 --- a/rust/src/section.rs +++ b/rust/src/section.rs @@ -84,7 +84,7 @@ impl Section { /// let bv = binaryninja::load("example").unwrap(); /// bv.add_section(Section::builder("example", 0..1024).align(4).entry_size(4)) /// ``` - pub fn builder(name: S, range: Range) -> SectionBuilder { + pub fn builder(name: S, range: Range) -> SectionBuilder { SectionBuilder::new(name, range) } @@ -197,7 +197,7 @@ unsafe impl CoreArrayProviderInner for Section { } #[must_use] -pub struct SectionBuilder { +pub struct SectionBuilder { is_auto: bool, name: S, range: Range, @@ -210,7 +210,7 @@ pub struct SectionBuilder { info_data: u64, } -impl SectionBuilder { +impl SectionBuilder { pub fn new(name: S, range: Range) -> Self { Self { is_auto: false, @@ -267,51 +267,34 @@ impl SectionBuilder { } pub(crate) fn create(self, view: &BinaryView) { - let name = self.name.into_bytes_with_nul(); - let ty = self._ty.map(|s| s.into_bytes_with_nul()); - let linked_section = self.linked_section.map(|s| s.into_bytes_with_nul()); - let info_section = self.info_section.map(|s| s.into_bytes_with_nul()); + let ty = self._ty.as_ref().map(|s| s.as_cstr()); + let linked_section = self.linked_section.as_ref().map(|s| s.as_cstr()); + let info_section = self.info_section.as_ref().map(|s| s.as_cstr()); let start = self.range.start; let len = self.range.end.wrapping_sub(start); + let add_section = if self.is_auto { + BNAddAutoSection + } else { + BNAddUserSection + }; + + let nul_str = c"".as_ptr(); unsafe { - let nul_str = c"".as_ptr(); - let name_ptr = name.as_ref().as_ptr() as *mut _; - let ty_ptr = ty.map_or(nul_str, |s| s.as_ref().as_ptr() as *mut _); - let linked_section_ptr = - linked_section.map_or(nul_str, |s| s.as_ref().as_ptr() as *mut _); - let info_section_ptr = info_section.map_or(nul_str, |s| s.as_ref().as_ptr() as *mut _); - - if self.is_auto { - BNAddAutoSection( - view.handle, - name_ptr, - start, - len, - self.semantics.into(), - ty_ptr, - self.align, - self.entry_size, - linked_section_ptr, - info_section_ptr, - self.info_data, - ); - } else { - BNAddUserSection( - view.handle, - name_ptr, - start, - len, - self.semantics.into(), - ty_ptr, - self.align, - self.entry_size, - linked_section_ptr, - info_section_ptr, - self.info_data, - ); - } + add_section( + view.handle, + self.name.as_cstr().as_ptr(), + start, + len, + self.semantics.into(), + ty.map_or(nul_str, |s| s.as_ptr()), + self.align, + self.entry_size, + linked_section.map_or(nul_str, |s| s.as_ptr()), + info_section.map_or(nul_str, |s| s.as_ptr()), + self.info_data, + ) } } } diff --git a/rust/src/settings.rs b/rust/src/settings.rs index 8bc8565f1..633aabe2c 100644 --- a/rust/src/settings.rs +++ b/rust/src/settings.rs @@ -20,7 +20,7 @@ use std::fmt::Debug; use crate::binary_view::BinaryView; use crate::rc::*; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; use crate::function::Function; @@ -44,48 +44,36 @@ impl Settings { Self::new_with_id(GLOBAL_INSTANCE_ID) } - pub fn new_with_id(instance_id: S) -> Ref { - let instance_id = instance_id.into_bytes_with_nul(); + pub fn new_with_id(instance_id: S) -> Ref { unsafe { - let handle = BNCreateSettings(instance_id.as_ref().as_ptr() as *mut _); + let handle = BNCreateSettings(instance_id.as_cstr().as_ptr()); debug_assert!(!handle.is_null()); Ref::new(Self { handle }) } } - pub fn set_resource_id(&self, resource_id: S) { - let resource_id = resource_id.into_bytes_with_nul(); - unsafe { BNSettingsSetResourceId(self.handle, resource_id.as_ref().as_ptr() as *mut _) }; + pub fn set_resource_id(&self, resource_id: S) { + unsafe { BNSettingsSetResourceId(self.handle, resource_id.as_cstr().as_ptr()) } } pub fn serialize_schema(&self) -> BnString { unsafe { BnString::from_raw(BNSettingsSerializeSchema(self.handle)) } } - pub fn deserialize_schema(&self, schema: S) -> bool { + pub fn deserialize_schema(&self, schema: S) -> bool { self.deserialize_schema_with_scope(schema, SettingsScope::SettingsAutoScope) } - pub fn deserialize_schema_with_scope( + pub fn deserialize_schema_with_scope( &self, schema: S, scope: SettingsScope, ) -> bool { - let schema = schema.into_bytes_with_nul(); - unsafe { - BNSettingsDeserializeSchema( - self.handle, - schema.as_ref().as_ptr() as *mut _, - scope, - true, - ) - } + unsafe { BNSettingsDeserializeSchema(self.handle, schema.as_cstr().as_ptr(), scope, true) } } - pub fn contains(&self, key: S) -> bool { - let key = key.into_bytes_with_nul(); - - unsafe { BNSettingsContains(self.handle, key.as_ref().as_ptr() as *mut _) } + pub fn contains(&self, key: S) -> bool { + unsafe { BNSettingsContains(self.handle, key.as_cstr().as_ptr()) } } pub fn keys(&self) -> Array { @@ -97,16 +85,11 @@ impl Settings { // TODO Update the settings API to take an optional BinaryView or Function. Separate functions or...? - pub fn get_bool(&self, key: S) -> bool { + pub fn get_bool(&self, key: S) -> bool { self.get_bool_with_opts(key, &mut QueryOptions::default()) } - pub fn get_bool_with_opts( - &self, - key: S, - options: &mut QueryOptions, - ) -> bool { - let key = key.into_bytes_with_nul(); + pub fn get_bool_with_opts(&self, key: S, options: &mut QueryOptions) -> bool { let view_ptr = match options.view.as_ref() { Some(view) => view.handle, _ => std::ptr::null_mut(), @@ -118,7 +101,7 @@ impl Settings { unsafe { BNSettingsGetBool( self.handle, - key.as_ref().as_ptr() as *mut _, + key.as_cstr().as_ptr(), view_ptr, func_ptr, &mut options.scope, @@ -126,16 +109,11 @@ impl Settings { } } - pub fn get_double(&self, key: S) -> f64 { + pub fn get_double(&self, key: S) -> f64 { self.get_double_with_opts(key, &mut QueryOptions::default()) } - pub fn get_double_with_opts( - &self, - key: S, - options: &mut QueryOptions, - ) -> f64 { - let key = key.into_bytes_with_nul(); + pub fn get_double_with_opts(&self, key: S, options: &mut QueryOptions) -> f64 { let view_ptr = match options.view.as_ref() { Some(view) => view.handle, _ => std::ptr::null_mut(), @@ -147,7 +125,7 @@ impl Settings { unsafe { BNSettingsGetDouble( self.handle, - key.as_ref().as_ptr() as *mut _, + key.as_cstr().as_ptr(), view_ptr, func_ptr, &mut options.scope, @@ -155,16 +133,11 @@ impl Settings { } } - pub fn get_integer(&self, key: S) -> u64 { + pub fn get_integer(&self, key: S) -> u64 { self.get_integer_with_opts(key, &mut QueryOptions::default()) } - pub fn get_integer_with_opts( - &self, - key: S, - options: &mut QueryOptions, - ) -> u64 { - let key = key.into_bytes_with_nul(); + pub fn get_integer_with_opts(&self, key: S, options: &mut QueryOptions) -> u64 { let view_ptr = match options.view.as_ref() { Some(view) => view.handle, _ => std::ptr::null_mut(), @@ -176,7 +149,7 @@ impl Settings { unsafe { BNSettingsGetUInt64( self.handle, - key.as_ref().as_ptr() as *mut _, + key.as_cstr().as_ptr(), view_ptr, func_ptr, &mut options.scope, @@ -184,16 +157,11 @@ impl Settings { } } - pub fn get_string(&self, key: S) -> BnString { + pub fn get_string(&self, key: S) -> BnString { self.get_string_with_opts(key, &mut QueryOptions::default()) } - pub fn get_string_with_opts( - &self, - key: S, - options: &mut QueryOptions, - ) -> BnString { - let key = key.into_bytes_with_nul(); + pub fn get_string_with_opts(&self, key: S, options: &mut QueryOptions) -> BnString { let view_ptr = match options.view.as_ref() { Some(view) => view.handle, _ => std::ptr::null_mut(), @@ -205,7 +173,7 @@ impl Settings { unsafe { BnString::from_raw(BNSettingsGetString( self.handle, - key.as_ref().as_ptr() as *mut _, + key.as_cstr().as_ptr(), view_ptr, func_ptr, &mut options.scope, @@ -213,16 +181,15 @@ impl Settings { } } - pub fn get_string_list(&self, key: S) -> Array { + pub fn get_string_list(&self, key: S) -> Array { self.get_string_list_with_opts(key, &mut QueryOptions::default()) } - pub fn get_string_list_with_opts( + pub fn get_string_list_with_opts( &self, key: S, options: &mut QueryOptions, ) -> Array { - let key = key.into_bytes_with_nul(); let view_ptr = match options.view.as_ref() { Some(view) => view.handle, _ => std::ptr::null_mut(), @@ -236,7 +203,7 @@ impl Settings { Array::new( BNSettingsGetStringList( self.handle, - key.as_ref().as_ptr() as *mut _, + key.as_cstr().as_ptr(), view_ptr, func_ptr, &mut options.scope, @@ -248,16 +215,11 @@ impl Settings { } } - pub fn get_json(&self, key: S) -> BnString { + pub fn get_json(&self, key: S) -> BnString { self.get_json_with_opts(key, &mut QueryOptions::default()) } - pub fn get_json_with_opts( - &self, - key: S, - options: &mut QueryOptions, - ) -> BnString { - let key = key.into_bytes_with_nul(); + pub fn get_json_with_opts(&self, key: S, options: &mut QueryOptions) -> BnString { let view_ptr = match options.view.as_ref() { Some(view) => view.handle, _ => std::ptr::null_mut(), @@ -269,7 +231,7 @@ impl Settings { unsafe { BnString::from_raw(BNSettingsGetJson( self.handle, - key.as_ref().as_ptr() as *mut _, + key.as_cstr().as_ptr(), view_ptr, func_ptr, &mut options.scope, @@ -277,17 +239,11 @@ impl Settings { } } - pub fn set_bool(&self, key: S, value: bool) { + pub fn set_bool(&self, key: S, value: bool) { self.set_bool_with_opts(key, value, &QueryOptions::default()) } - pub fn set_bool_with_opts( - &self, - key: S, - value: bool, - options: &QueryOptions, - ) { - let key = key.into_bytes_with_nul(); + pub fn set_bool_with_opts(&self, key: S, value: bool, options: &QueryOptions) { let view_ptr = match options.view.as_ref() { Some(view) => view.handle, _ => std::ptr::null_mut(), @@ -302,22 +258,16 @@ impl Settings { view_ptr, func_ptr, options.scope, - key.as_ref().as_ptr() as *mut _, + key.as_cstr().as_ptr(), value, ); } } - pub fn set_double(&self, key: S, value: f64) { + pub fn set_double(&self, key: S, value: f64) { self.set_double_with_opts(key, value, &QueryOptions::default()) } - pub fn set_double_with_opts( - &self, - key: S, - value: f64, - options: &QueryOptions, - ) { - let key = key.into_bytes_with_nul(); + pub fn set_double_with_opts(&self, key: S, value: f64, options: &QueryOptions) { let view_ptr = match options.view.as_ref() { Some(view) => view.handle, _ => std::ptr::null_mut(), @@ -332,23 +282,17 @@ impl Settings { view_ptr, func_ptr, options.scope, - key.as_ref().as_ptr() as *mut _, + key.as_cstr().as_ptr(), value, ); } } - pub fn set_integer(&self, key: S, value: u64) { + pub fn set_integer(&self, key: S, value: u64) { self.set_integer_with_opts(key, value, &QueryOptions::default()) } - pub fn set_integer_with_opts( - &self, - key: S, - value: u64, - options: &QueryOptions, - ) { - let key = key.into_bytes_with_nul(); + pub fn set_integer_with_opts(&self, key: S, value: u64, options: &QueryOptions) { let view_ptr = match options.view.as_ref() { Some(view) => view.handle, _ => std::ptr::null_mut(), @@ -363,24 +307,22 @@ impl Settings { view_ptr, func_ptr, options.scope, - key.as_ref().as_ptr() as *mut _, + key.as_cstr().as_ptr(), value, ); } } - pub fn set_string(&self, key: S1, value: S2) { + pub fn set_string(&self, key: S1, value: S2) { self.set_string_with_opts(key, value, &QueryOptions::default()) } - pub fn set_string_with_opts( + pub fn set_string_with_opts( &self, key: S1, value: S2, options: &QueryOptions, ) { - let key = key.into_bytes_with_nul(); - let value = value.into_bytes_with_nul(); let view_ptr = match options.view.as_ref() { Some(view) => view.handle, _ => std::ptr::null_mut(), @@ -395,13 +337,13 @@ impl Settings { view_ptr, func_ptr, options.scope, - key.as_ref().as_ptr() as *mut _, - value.as_ref().as_ptr() as *mut _, + key.as_cstr().as_ptr(), + value.as_cstr().as_ptr(), ); } } - pub fn set_string_list>( + pub fn set_string_list>( &self, key: S1, value: I, @@ -409,22 +351,15 @@ impl Settings { self.set_string_list_with_opts(key, value, &QueryOptions::default()) } - pub fn set_string_list_with_opts< - S1: BnStrCompatible, - S2: BnStrCompatible, - I: Iterator, - >( + pub fn set_string_list_with_opts>( &self, key: S1, value: I, options: &QueryOptions, ) -> bool { - let key = key.into_bytes_with_nul(); - let raw_list: Vec<_> = value.map(|s| s.into_bytes_with_nul()).collect(); - let mut raw_list_ptr: Vec<_> = raw_list - .iter() - .map(|s| s.as_ref().as_ptr() as *const c_char) - .collect(); + let value = value.collect::>(); + let raw_list: Vec<_> = value.iter().map(|s| s.as_cstr()).collect(); + let mut raw_list_ptr: Vec<_> = raw_list.iter().map(|s| s.as_ptr()).collect(); let view_ptr = match options.view.as_ref() { Some(view) => view.handle, @@ -440,25 +375,23 @@ impl Settings { view_ptr, func_ptr, options.scope, - key.as_ref().as_ptr() as *mut _, + key.as_cstr().as_ptr(), raw_list_ptr.as_mut_ptr(), raw_list_ptr.len(), ) } } - pub fn set_json(&self, key: S1, value: S2) -> bool { + pub fn set_json(&self, key: S1, value: S2) -> bool { self.set_json_with_opts(key, value, &QueryOptions::default()) } - pub fn set_json_with_opts( + pub fn set_json_with_opts( &self, key: S1, value: S2, options: &QueryOptions, ) -> bool { - let key = key.into_bytes_with_nul(); - let value = value.into_bytes_with_nul(); let view_ptr = match options.view.as_ref() { Some(view) => view.handle, _ => std::ptr::null_mut(), @@ -473,38 +406,30 @@ impl Settings { view_ptr, func_ptr, options.scope, - key.as_ref().as_ptr() as *mut _, - value.as_ref().as_ptr() as *mut _, + key.as_cstr().as_ptr(), + value.as_cstr().as_ptr(), ) } } - pub fn get_property_string(&self, key: S, property: S) -> BnString { - let key = key.into_bytes_with_nul(); - let property = property.into_bytes_with_nul(); + pub fn get_property_string(&self, key: S, property: S) -> BnString { unsafe { BnString::from_raw(BNSettingsQueryPropertyString( self.handle, - key.as_ref().as_ptr() as *mut _, - property.as_ref().as_ptr() as *mut _, + key.as_cstr().as_ptr(), + property.as_cstr().as_ptr(), )) } } - pub fn get_property_string_list( - &self, - key: S, - property: S, - ) -> Array { - let key = key.into_bytes_with_nul(); - let property = property.into_bytes_with_nul(); + pub fn get_property_string_list(&self, key: S, property: S) -> Array { let mut size: usize = 0; unsafe { Array::new( BNSettingsQueryPropertyStringList( self.handle, - key.as_ref().as_ptr() as *mut _, - property.as_ref().as_ptr() as *mut _, + key.as_cstr().as_ptr(), + property.as_cstr().as_ptr(), &mut size, ) as *mut *mut c_char, size, @@ -513,114 +438,87 @@ impl Settings { } } - pub fn update_bool_property(&self, key: S, property: S, value: bool) { - let key = key.into_bytes_with_nul(); - let property = property.into_bytes_with_nul(); + pub fn update_bool_property(&self, key: S, property: S, value: bool) { unsafe { BNSettingsUpdateBoolProperty( self.handle, - key.as_ref().as_ptr() as *mut _, - property.as_ref().as_ptr() as *mut _, + key.as_cstr().as_ptr(), + property.as_cstr().as_ptr(), value, ); } } - pub fn update_integer_property(&self, key: S, property: S, value: u64) { - let key = key.into_bytes_with_nul(); - let property = property.into_bytes_with_nul(); + pub fn update_integer_property(&self, key: S, property: S, value: u64) { unsafe { BNSettingsUpdateUInt64Property( self.handle, - key.as_ref().as_ptr() as *mut _, - property.as_ref().as_ptr() as *mut _, + key.as_cstr().as_ptr(), + property.as_cstr().as_ptr(), value, ); } } - pub fn update_double_property(&self, key: S, property: S, value: f64) { - let key = key.into_bytes_with_nul(); - let property = property.into_bytes_with_nul(); + pub fn update_double_property(&self, key: S, property: S, value: f64) { unsafe { BNSettingsUpdateDoubleProperty( self.handle, - key.as_ref().as_ptr() as *mut _, - property.as_ref().as_ptr() as *mut _, + key.as_cstr().as_ptr(), + property.as_cstr().as_ptr(), value, ); } } - pub fn update_string_property(&self, key: S, property: S, value: S) { - let key = key.into_bytes_with_nul(); - let property = property.into_bytes_with_nul(); - let value = value.into_bytes_with_nul(); + pub fn update_string_property(&self, key: S, property: S, value: S) { unsafe { BNSettingsUpdateStringProperty( self.handle, - key.as_ref().as_ptr() as *mut _, - property.as_ref().as_ptr() as *mut _, - value.as_ref().as_ptr() as *mut _, + key.as_cstr().as_ptr(), + property.as_cstr().as_ptr(), + value.as_cstr().as_ptr(), ); } } - pub fn update_string_list_property>( + pub fn update_string_list_property>( &self, key: S, property: S, value: I, ) { - let key = key.into_bytes_with_nul(); - let property = property.into_bytes_with_nul(); - let raw_list: Vec<_> = value.map(|s| s.into_bytes_with_nul()).collect(); - let mut raw_list_ptr: Vec<_> = raw_list - .iter() - .map(|s| s.as_ref().as_ptr() as *const c_char) - .collect(); + let value = value.collect::>(); + let raw_list: Vec<_> = value.iter().map(|s| s.as_cstr()).collect(); + let mut raw_list_ptr: Vec<_> = raw_list.iter().map(|s| s.as_ptr()).collect(); unsafe { BNSettingsUpdateStringListProperty( self.handle, - key.as_ref().as_ptr() as *mut _, - property.as_ref().as_ptr() as *mut _, + key.as_cstr().as_ptr(), + property.as_cstr().as_ptr(), raw_list_ptr.as_mut_ptr(), raw_list_ptr.len(), ); } } - pub fn register_group( - &self, - group: S1, - title: S2, - ) -> bool { - let group = group.into_bytes_with_nul(); - let title = title.into_bytes_with_nul(); - + pub fn register_group(&self, group: S1, title: S2) -> bool { unsafe { BNSettingsRegisterGroup( self.handle, - group.as_ref().as_ptr() as *mut _, - title.as_ref().as_ptr() as *mut _, + group.as_cstr().as_ptr(), + title.as_cstr().as_ptr(), ) } } - pub fn register_setting_json( - &self, - group: S1, - properties: S2, - ) -> bool { - let group = group.into_bytes_with_nul(); - let properties = properties.into_bytes_with_nul(); - + pub fn register_setting_json(&self, group: S1, properties: S2) -> bool { unsafe { BNSettingsRegisterSetting( self.handle, - group.as_ref().as_ptr() as *mut _, - properties.as_ref().as_ptr() as *mut _, + group.as_cstr().as_ptr(), + properties.as_cstr().as_ptr(), ) } } diff --git a/rust/src/string.rs b/rust/src/string.rs index dde8f5507..c5bf05f14 100644 --- a/rust/src/string.rs +++ b/rust/src/string.rs @@ -21,7 +21,6 @@ use std::ffi::{c_char, CStr, CString}; use std::fmt; use std::hash::{Hash, Hasher}; use std::mem; -use std::ops::Deref; use std::path::{Path, PathBuf}; // TODO: Remove or refactor this. @@ -44,29 +43,23 @@ pub(crate) fn strings_to_string_list(strings: &[String]) -> *mut *mut c_char { unsafe { BNAllocStringList(raw_str_list.as_mut_ptr(), raw_str_list.len()) } } -/// Is the equivalent of `core::ffi::CString` but using the alloc and free from `binaryninjacore-sys`. +/// A nul-terminated C string allocated by the core. +/// +/// Received from a variety of core function calls, and must be used when giving strings to the +/// core from many core-invoked callbacks. +/// +/// These are strings we're responsible for freeing, such as strings allocated by the core and +/// given to us through the API and then forgotten about by the core. #[repr(transparent)] pub struct BnString { raw: *mut c_char, } -/// A nul-terminated C string allocated by the core. -/// -/// Received from a variety of core function calls, and -/// must be used when giving strings to the core from many -/// core-invoked callbacks. -/// -/// These are strings we're responsible for freeing, such as -/// strings allocated by the core and given to us through the API -/// and then forgotten about by the core. impl BnString { - pub fn new(s: S) -> Self { + pub fn new(s: S) -> Self { use binaryninjacore_sys::BNAllocString; - let raw = s.into_bytes_with_nul(); - unsafe { - let ptr = raw.as_ref().as_ptr() as *mut _; - Self::from_raw(BNAllocString(ptr)) - } + let raw = s.as_cstr(); + unsafe { Self::from_raw(BNAllocString(raw.as_ptr())) } } /// Construct a BnString from an owned const char* allocated by BNAllocString @@ -76,36 +69,40 @@ impl BnString { /// Consumes the `BnString`, returning a raw pointer to the string. /// - /// After calling this function, the caller is responsible for the - /// memory previously managed by the `BnString`. + /// After calling this function, the caller is responsible for freeing the memory previously + /// managed by the `BnString`. /// - /// This is typically used to pass a string back through the core where the core is expected to free. + /// This is typically used to pass a string back through the core where the core is expected to + /// free. pub fn into_raw(value: Self) -> *mut c_char { let res = value.raw; - // we're surrendering ownership over the *mut c_char to - // the core, so ensure we don't free it + // surrendering ownership of the pointer to the core, so ensure we don't free it mem::forget(value); res } + pub fn as_c_str(&self) -> &CStr { + unsafe { CStr::from_ptr(self.raw) } + } + pub fn as_str(&self) -> &str { - unsafe { CStr::from_ptr(self.raw).to_str().unwrap() } + self.as_c_str().to_str().unwrap() } pub fn as_bytes(&self) -> &[u8] { - self.as_str().as_bytes() + self.as_c_str().to_bytes() } - pub fn as_bytes_with_null(&self) -> &[u8] { - self.deref().to_bytes() + pub fn as_ptr(&self) -> *const c_char { + self.raw } pub fn len(&self) -> usize { - self.as_ref().len() + self.as_bytes().len() } pub fn is_empty(&self) -> bool { - self.as_ref().is_empty() + self.as_bytes().is_empty() } } @@ -129,29 +126,27 @@ impl Clone for BnString { } } -impl Deref for BnString { - type Target = CStr; - - fn deref(&self) -> &CStr { - unsafe { CStr::from_ptr(self.raw) } +impl Hash for BnString { + fn hash(&self, state: &mut H) { + self.raw.hash(state) } } -impl AsRef<[u8]> for BnString { - fn as_ref(&self) -> &[u8] { - self.to_bytes_with_nul() +impl PartialEq for BnString { + fn eq(&self, other: &Self) -> bool { + self.as_c_str() == other.as_c_str() } } -impl Hash for BnString { - fn hash(&self, state: &mut H) { - self.raw.hash(state) +impl PartialEq for BnString { + fn eq(&self, other: &CStr) -> bool { + self.as_c_str() == other } } -impl PartialEq for BnString { - fn eq(&self, other: &Self) -> bool { - self.deref() == other.deref() +impl PartialEq for BnString { + fn eq(&self, other: &str) -> bool { + self.as_str() == other } } @@ -159,13 +154,13 @@ impl Eq for BnString {} impl fmt::Display for BnString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.to_string_lossy()) + write!(f, "{}", self.as_c_str().to_string_lossy()) } } impl fmt::Debug for BnString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.to_string_lossy()) + fmt::Display::fmt(self, f) } } @@ -186,109 +181,83 @@ unsafe impl CoreArrayProviderInner for BnString { } } -pub unsafe trait BnStrCompatible { - type Result: AsRef<[u8]>; - - fn into_bytes_with_nul(self) -> Self::Result; +pub trait AsCStr { + fn as_cstr(&self) -> Cow<'_, CStr>; } -unsafe impl<'a> BnStrCompatible for &'a CStr { - type Result = &'a [u8]; - - fn into_bytes_with_nul(self) -> Self::Result { - self.to_bytes_with_nul() +impl AsCStr for CStr { + fn as_cstr(&self) -> Cow<'_, CStr> { + self.into() } } -unsafe impl BnStrCompatible for BnString { - type Result = Self; - - fn into_bytes_with_nul(self) -> Self::Result { - self +impl AsCStr for CString { + fn as_cstr(&self) -> Cow<'_, CStr> { + self.into() } } -unsafe impl BnStrCompatible for CString { - type Result = Vec; - - fn into_bytes_with_nul(self) -> Self::Result { - self.into_bytes_with_nul() +impl AsCStr for BnString { + fn as_cstr(&self) -> Cow<'_, CStr> { + self.as_c_str().into() } } -unsafe impl BnStrCompatible for &str { - type Result = Vec; - - fn into_bytes_with_nul(self) -> Self::Result { - let ret = CString::new(self).expect("can't pass strings with internal nul bytes to core!"); - ret.into_bytes_with_nul() +impl AsCStr for str { + fn as_cstr(&self) -> Cow<'_, CStr> { + CString::new(self) + .expect("can't pass strings with internal null bytes to the core!") + .into() } } -unsafe impl BnStrCompatible for String { - type Result = Vec; - - fn into_bytes_with_nul(self) -> Self::Result { - self.as_str().into_bytes_with_nul() +impl AsCStr for String { + fn as_cstr(&self) -> Cow<'_, CStr> { + self.as_str().as_cstr() } } -unsafe impl BnStrCompatible for &String { - type Result = Vec; - - fn into_bytes_with_nul(self) -> Self::Result { - self.as_str().into_bytes_with_nul() +impl AsCStr for Cow<'_, str> { + fn as_cstr(&self) -> Cow<'_, CStr> { + self.as_ref().as_cstr() } } -unsafe impl<'a> BnStrCompatible for &'a Cow<'a, str> { - type Result = Vec; - - fn into_bytes_with_nul(self) -> Self::Result { - self.to_string().into_bytes_with_nul() +impl AsCStr for Path { + fn as_cstr(&self) -> Cow<'_, CStr> { + CString::new(self.as_os_str().as_encoded_bytes()) + .expect("can't pass paths with internal null bytes to the core!") + .into() } } -unsafe impl BnStrCompatible for Cow<'_, str> { - type Result = Vec; - - fn into_bytes_with_nul(self) -> Self::Result { - self.to_string().into_bytes_with_nul() +impl AsCStr for PathBuf { + fn as_cstr(&self) -> Cow<'_, CStr> { + self.as_path().as_cstr() } } -unsafe impl BnStrCompatible for &QualifiedName { - type Result = Vec; - - fn into_bytes_with_nul(self) -> Self::Result { - self.to_string().into_bytes_with_nul() +impl AsCStr for QualifiedName { + fn as_cstr(&self) -> Cow<'_, CStr> { + // Simply deferring to `self.to_string().as_cstr()` makes the borrow checker angry + CString::new(self.to_string()).unwrap().into() } } -unsafe impl BnStrCompatible for PathBuf { - type Result = Vec; - - fn into_bytes_with_nul(self) -> Self::Result { - self.as_path().into_bytes_with_nul() - } -} - -unsafe impl BnStrCompatible for &Path { - type Result = Vec; - - fn into_bytes_with_nul(self) -> Self::Result { - self.as_os_str().as_encoded_bytes().to_vec() +impl AsCStr for &T { + fn as_cstr(&self) -> Cow<'_, CStr> { + (*self).as_cstr() } } pub trait IntoJson { - type Output: BnStrCompatible; + type Output: AsCStr; fn get_json_string(self) -> Result; } -impl IntoJson for S { - type Output = S; +impl IntoJson for S { + type Output = Self; fn get_json_string(self) -> Result { Ok(self) diff --git a/rust/src/symbol.rs b/rust/src/symbol.rs index 21df31a7e..0ef38e9bd 100644 --- a/rust/src/symbol.rs +++ b/rust/src/symbol.rs @@ -152,64 +152,27 @@ impl SymbolBuilder { } pub fn create(self) -> Ref { - let raw_name = self.raw_name.into_bytes_with_nul(); - let short_name = self.short_name.map(|s| s.into_bytes_with_nul()); - let full_name = self.full_name.map(|s| s.into_bytes_with_nul()); + let raw_name = self.raw_name.as_cstr(); + let short_name = self + .short_name + .as_ref() + .map_or_else(|| raw_name.clone(), |s| s.as_cstr()); + let full_name = self + .full_name + .as_ref() + .map_or_else(|| raw_name.clone(), |s| s.as_cstr()); - // Lifetimes, man - let raw_name = raw_name.as_ptr() as _; unsafe { - if let Some(short_name) = short_name { - if let Some(full_name) = full_name { - let res = BNCreateSymbol( - self.ty.into(), - short_name.as_ptr() as _, - full_name.as_ptr() as _, - raw_name, - self.addr, - self.binding.into(), - ptr::null_mut(), - self.ordinal, - ); - Symbol::ref_from_raw(res) - } else { - let res = BNCreateSymbol( - self.ty.into(), - short_name.as_ptr() as _, - raw_name, - raw_name, - self.addr, - self.binding.into(), - ptr::null_mut(), - self.ordinal, - ); - Symbol::ref_from_raw(res) - } - } else if let Some(full_name) = full_name { - let res = BNCreateSymbol( - self.ty.into(), - raw_name, - full_name.as_ptr() as _, - raw_name, - self.addr, - self.binding.into(), - ptr::null_mut(), - self.ordinal, - ); - Symbol::ref_from_raw(res) - } else { - let res = BNCreateSymbol( - self.ty.into(), - raw_name, - raw_name, - raw_name, - self.addr, - self.binding.into(), - ptr::null_mut(), - self.ordinal, - ); - Symbol::ref_from_raw(res) - } + Symbol::ref_from_raw(BNCreateSymbol( + self.ty.into(), + short_name.as_ptr(), + full_name.as_ptr(), + raw_name.as_ptr(), + self.addr, + self.binding.into(), + ptr::null_mut(), + self.ordinal, + )) } } } diff --git a/rust/src/tags.rs b/rust/src/tags.rs index b378f7edf..1aa0af6d7 100644 --- a/rust/src/tags.rs +++ b/rust/src/tags.rs @@ -42,9 +42,8 @@ impl Tag { Ref::new(Self { handle }) } - pub fn new(t: &TagType, data: S) -> Ref { - let data = data.into_bytes_with_nul(); - unsafe { Self::ref_from_raw(BNCreateTag(t.handle, data.as_ref().as_ptr() as *mut _)) } + pub fn new(t: &TagType, data: S) -> Ref { + unsafe { Self::ref_from_raw(BNCreateTag(t.handle, data.as_cstr().as_ptr())) } } pub fn id(&self) -> BnString { @@ -59,11 +58,8 @@ impl Tag { unsafe { TagType::ref_from_raw(BNTagGetType(self.handle)) } } - pub fn set_data(&self, data: S) { - let data = data.into_bytes_with_nul(); - unsafe { - BNTagSetData(self.handle, data.as_ref().as_ptr() as *mut _); - } + pub fn set_data(&self, data: S) { + unsafe { BNTagSetData(self.handle, data.as_cstr().as_ptr()) } } } @@ -134,11 +130,7 @@ impl TagType { Ref::new(Self { handle }) } - pub fn create( - view: &BinaryView, - name: N, - icon: I, - ) -> Ref { + pub fn create(view: &BinaryView, name: N, icon: I) -> Ref { let tag_type = unsafe { Self::ref_from_raw(BNCreateTagType(view.handle)) }; tag_type.set_name(name); tag_type.set_icon(icon); @@ -153,22 +145,16 @@ impl TagType { unsafe { BnString::from_raw(BNTagTypeGetIcon(self.handle)) } } - pub fn set_icon(&self, icon: S) { - let icon = icon.into_bytes_with_nul(); - unsafe { - BNTagTypeSetIcon(self.handle, icon.as_ref().as_ptr() as *mut _); - } + pub fn set_icon(&self, icon: S) { + unsafe { BNTagTypeSetIcon(self.handle, icon.as_cstr().as_ptr()) } } pub fn name(&self) -> BnString { unsafe { BnString::from_raw(BNTagTypeGetName(self.handle)) } } - pub fn set_name(&self, name: S) { - let name = name.into_bytes_with_nul(); - unsafe { - BNTagTypeSetName(self.handle, name.as_ref().as_ptr() as *mut _); - } + pub fn set_name(&self, name: S) { + unsafe { BNTagTypeSetName(self.handle, name.as_cstr().as_ptr()) } } pub fn visible(&self) -> bool { @@ -183,11 +169,8 @@ impl TagType { unsafe { BNTagTypeGetType(self.handle) } } - pub fn set_type(&self, t: S) { - let t = t.into_bytes_with_nul(); - unsafe { - BNTagTypeSetName(self.handle, t.as_ref().as_ptr() as *mut _); - } + pub fn set_type(&self, t: S) { + unsafe { BNTagTypeSetName(self.handle, t.as_cstr().as_ptr()) } } pub fn view(&self) -> Ref { diff --git a/rust/src/template_simplifier.rs b/rust/src/template_simplifier.rs index dd815f69a..615ffd327 100644 --- a/rust/src/template_simplifier.rs +++ b/rust/src/template_simplifier.rs @@ -1,20 +1,15 @@ use crate::{ - string::{BnStrCompatible, BnString}, + string::{AsCStr, BnString}, types::QualifiedName, }; use binaryninjacore_sys::{BNRustSimplifyStrToFQN, BNRustSimplifyStrToStr}; -pub fn simplify_str_to_str(input: S) -> BnString { - let name = input.into_bytes_with_nul(); - unsafe { BnString::from_raw(BNRustSimplifyStrToStr(name.as_ref().as_ptr() as *mut _)) } +pub fn simplify_str_to_str(input: S) -> BnString { + unsafe { BnString::from_raw(BNRustSimplifyStrToStr(input.as_cstr().as_ptr())) } } -pub fn simplify_str_to_fqn(input: S, simplify: bool) -> QualifiedName { - let name = input.into_bytes_with_nul(); +pub fn simplify_str_to_fqn(input: S, simplify: bool) -> QualifiedName { unsafe { - QualifiedName::from_owned_raw(BNRustSimplifyStrToFQN( - name.as_ref().as_ptr() as *mut _, - simplify, - )) + QualifiedName::from_owned_raw(BNRustSimplifyStrToFQN(input.as_cstr().as_ptr(), simplify)) } } diff --git a/rust/src/type_archive.rs b/rust/src/type_archive.rs index 8d2671580..fc42dcf3c 100644 --- a/rust/src/type_archive.rs +++ b/rust/src/type_archive.rs @@ -10,7 +10,7 @@ use crate::metadata::Metadata; use crate::platform::Platform; use crate::progress::ProgressExecutor; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{raw_to_string, BnStrCompatible, BnString}; +use crate::string::{raw_to_string, AsCStr, BnString}; use crate::type_container::TypeContainer; use crate::types::{QualifiedName, QualifiedNameAndType, QualifiedNameTypeAndId, Type}; @@ -65,8 +65,7 @@ impl TypeArchive { /// Open the Type Archive at the given path, if it exists. pub fn open(path: impl AsRef) -> Option> { - let raw_path = path.as_ref().into_bytes_with_nul(); - let handle = unsafe { BNOpenTypeArchive(raw_path.as_ptr() as *const c_char) }; + let handle = unsafe { BNOpenTypeArchive(path.as_ref().as_cstr().as_ptr()) }; NonNull::new(handle).map(|handle| unsafe { TypeArchive::ref_from_raw(handle) }) } @@ -74,36 +73,32 @@ impl TypeArchive { /// /// If the file has already been created and is not a valid type archive this will return `None`. pub fn create(path: impl AsRef, platform: &Platform) -> Option> { - let raw_path = path.as_ref().into_bytes_with_nul(); let handle = - unsafe { BNCreateTypeArchive(raw_path.as_ptr() as *const c_char, platform.handle) }; + unsafe { BNCreateTypeArchive(path.as_ref().as_cstr().as_ptr(), platform.handle) }; NonNull::new(handle).map(|handle| unsafe { TypeArchive::ref_from_raw(handle) }) } /// Create a Type Archive at the given path and id, returning None if it could not be created. /// /// If the file has already been created and is not a valid type archive this will return `None`. - pub fn create_with_id( + pub fn create_with_id( path: impl AsRef, id: I, platform: &Platform, ) -> Option> { - let raw_path = path.as_ref().into_bytes_with_nul(); - let id = id.into_bytes_with_nul(); let handle = unsafe { BNCreateTypeArchiveWithId( - raw_path.as_ptr() as *const c_char, + path.as_ref().as_cstr().as_ptr(), platform.handle, - id.as_ref().as_ptr() as *const c_char, + id.as_cstr().as_ptr(), ) }; NonNull::new(handle).map(|handle| unsafe { TypeArchive::ref_from_raw(handle) }) } /// Get a reference to the Type Archive with the known id, if one exists. - pub fn lookup_by_id(id: S) -> Option> { - let id = id.into_bytes_with_nul(); - let handle = unsafe { BNLookupTypeArchiveById(id.as_ref().as_ptr() as *const c_char) }; + pub fn lookup_by_id(id: S) -> Option> { + let handle = unsafe { BNLookupTypeArchiveById(id.as_cstr().as_ptr()) }; NonNull::new(handle).map(|handle| unsafe { TypeArchive::ref_from_raw(handle) }) } @@ -155,7 +150,7 @@ impl TypeArchive { } /// Get the ids of the parents to the given snapshot - pub fn get_snapshot_parent_ids( + pub fn get_snapshot_parent_ids( &self, snapshot: &TypeArchiveSnapshotId, ) -> Option> { @@ -171,7 +166,7 @@ impl TypeArchive { } /// Get the ids of the children to the given snapshot - pub fn get_snapshot_child_ids( + pub fn get_snapshot_child_ids( &self, snapshot: &TypeArchiveSnapshotId, ) -> Option> { @@ -223,26 +218,18 @@ impl TypeArchive { /// * `old_name` - Old type name in archive /// * `new_name` - New type name pub fn rename_type(&self, old_name: QualifiedName, new_name: QualifiedName) -> bool { - if let Some(id) = self.get_type_id(old_name) { - self.rename_type_by_id(id, new_name) - } else { - false - } + self.get_type_id(old_name) + .is_some_and(|id| self.rename_type_by_id(id, new_name)) } /// Change the name of an existing type in the type archive. Returns false if failed. /// /// * `id` - Old id of type in archive /// * `new_name` - New type name - pub fn rename_type_by_id(&self, id: S, new_name: QualifiedName) -> bool { - let id = id.into_bytes_with_nul(); + pub fn rename_type_by_id(&self, id: S, new_name: QualifiedName) -> bool { let raw_name = QualifiedName::into_raw(new_name); let result = unsafe { - BNRenameTypeArchiveType( - self.handle.as_ptr(), - id.as_ref().as_ptr() as *const c_char, - &raw_name, - ) + BNRenameTypeArchiveType(self.handle.as_ptr(), id.as_cstr().as_ptr(), &raw_name) }; QualifiedName::free_raw(raw_name); result @@ -250,26 +237,21 @@ impl TypeArchive { /// Delete an existing type in the type archive. pub fn delete_type(&self, name: QualifiedName) -> bool { - if let Some(type_id) = self.get_type_id(name) { - self.delete_type_by_id(type_id) - } else { - false - } + self.get_type_id(name) + .is_some_and(|id| self.delete_type_by_id(id)) } /// Delete an existing type in the type archive. - pub fn delete_type_by_id(&self, id: S) -> bool { - let id = id.into_bytes_with_nul(); - let result = unsafe { - BNDeleteTypeArchiveType(self.handle.as_ptr(), id.as_ref().as_ptr() as *const c_char) - }; + pub fn delete_type_by_id(&self, id: S) -> bool { + let result = + unsafe { BNDeleteTypeArchiveType(self.handle.as_ptr(), id.as_cstr().as_ptr()) }; result } /// Retrieve a stored type in the archive /// /// * `name` - Type name - pub fn get_type_by_name(&self, name: QualifiedName) -> Option> { + pub fn get_type_by_name(&self, name: QualifiedName) -> Option> { self.get_type_by_name_from_snapshot(name, &TypeArchiveSnapshotId::unset()) } @@ -297,7 +279,7 @@ impl TypeArchive { /// Retrieve a stored type in the archive by id /// /// * `id` - Type id - pub fn get_type_by_id(&self, id: I) -> Option> { + pub fn get_type_by_id(&self, id: I) -> Option> { self.get_type_by_id_from_snapshot(id, &TypeArchiveSnapshotId::unset()) } @@ -305,16 +287,15 @@ impl TypeArchive { /// /// * `id` - Type id /// * `snapshot` - Snapshot id to search for types - pub fn get_type_by_id_from_snapshot( + pub fn get_type_by_id_from_snapshot( &self, id: I, snapshot: &TypeArchiveSnapshotId, ) -> Option> { - let id = id.into_bytes_with_nul(); let result = unsafe { BNGetTypeArchiveTypeById( self.handle.as_ptr(), - id.as_ref().as_ptr() as *const c_char, + id.as_cstr().as_ptr(), snapshot.0.as_ptr() as *const c_char, ) }; @@ -324,7 +305,7 @@ impl TypeArchive { /// Retrieve a type's name by its id /// /// * `id` - Type id - pub fn get_type_name_by_id(&self, id: I) -> QualifiedName { + pub fn get_type_name_by_id(&self, id: I) -> QualifiedName { self.get_type_name_by_id_from_snapshot(id, &TypeArchiveSnapshotId::unset()) } @@ -332,16 +313,15 @@ impl TypeArchive { /// /// * `id` - Type id /// * `snapshot` - Snapshot id to search for types - pub fn get_type_name_by_id_from_snapshot( + pub fn get_type_name_by_id_from_snapshot( &self, id: I, snapshot: &TypeArchiveSnapshotId, ) -> QualifiedName { - let id = id.into_bytes_with_nul(); let result = unsafe { BNGetTypeArchiveTypeName( self.handle.as_ptr(), - id.as_ref().as_ptr() as *const c_char, + id.as_cstr().as_ptr(), snapshot.0.as_ptr() as *const c_char, ) }; @@ -478,7 +458,7 @@ impl TypeArchive { /// Get all types a given type references directly /// /// * `id` - Source type id - pub fn get_outgoing_direct_references(&self, id: I) -> Array { + pub fn get_outgoing_direct_references(&self, id: I) -> Array { self.get_outgoing_direct_references_from_snapshot(id, &TypeArchiveSnapshotId::unset()) } @@ -486,17 +466,16 @@ impl TypeArchive { /// /// * `id` - Source type id /// * `snapshot` - Snapshot id to search for types - pub fn get_outgoing_direct_references_from_snapshot( + pub fn get_outgoing_direct_references_from_snapshot( &self, id: I, snapshot: &TypeArchiveSnapshotId, ) -> Array { - let id = id.into_bytes_with_nul(); let mut count = 0; let result = unsafe { BNGetTypeArchiveOutgoingDirectTypeReferences( self.handle.as_ptr(), - id.as_ref().as_ptr() as *const c_char, + id.as_cstr().as_ptr(), snapshot.0.as_ptr() as *const c_char, &mut count, ) @@ -508,7 +487,7 @@ impl TypeArchive { /// Get all types a given type references, and any types that the referenced types reference /// /// * `id` - Source type id - pub fn get_outgoing_recursive_references(&self, id: I) -> Array { + pub fn get_outgoing_recursive_references(&self, id: I) -> Array { self.get_outgoing_recursive_references_from_snapshot(id, &TypeArchiveSnapshotId::unset()) } @@ -516,17 +495,16 @@ impl TypeArchive { /// /// * `id` - Source type id /// * `snapshot` - Snapshot id to search for types - pub fn get_outgoing_recursive_references_from_snapshot( + pub fn get_outgoing_recursive_references_from_snapshot( &self, id: I, snapshot: &TypeArchiveSnapshotId, ) -> Array { - let id = id.into_bytes_with_nul(); let mut count = 0; let result = unsafe { BNGetTypeArchiveOutgoingRecursiveTypeReferences( self.handle.as_ptr(), - id.as_ref().as_ptr() as *const c_char, + id.as_cstr().as_ptr(), snapshot.0.as_ptr() as *const c_char, &mut count, ) @@ -538,7 +516,7 @@ impl TypeArchive { /// Get all types that reference a given type /// /// * `id` - Target type id - pub fn get_incoming_direct_references(&self, id: I) -> Array { + pub fn get_incoming_direct_references(&self, id: I) -> Array { self.get_incoming_direct_references_with_snapshot(id, &TypeArchiveSnapshotId::unset()) } @@ -546,17 +524,16 @@ impl TypeArchive { /// /// * `id` - Target type id /// * `snapshot` - Snapshot id to search for types - pub fn get_incoming_direct_references_with_snapshot( + pub fn get_incoming_direct_references_with_snapshot( &self, id: I, snapshot: &TypeArchiveSnapshotId, ) -> Array { - let id = id.into_bytes_with_nul(); let mut count = 0; let result = unsafe { BNGetTypeArchiveIncomingDirectTypeReferences( self.handle.as_ptr(), - id.as_ref().as_ptr() as *const c_char, + id.as_cstr().as_ptr(), snapshot.0.as_ptr() as *const c_char, &mut count, ) @@ -568,7 +545,7 @@ impl TypeArchive { /// Get all types that reference a given type, and all types that reference them, recursively /// /// * `id` - Target type id - pub fn get_incoming_recursive_references(&self, id: I) -> Array { + pub fn get_incoming_recursive_references(&self, id: I) -> Array { self.get_incoming_recursive_references_with_snapshot(id, &TypeArchiveSnapshotId::unset()) } @@ -576,17 +553,16 @@ impl TypeArchive { /// /// * `id` - Target type id /// * `snapshot` - Snapshot id to search for types, or empty string to search the latest snapshot - pub fn get_incoming_recursive_references_with_snapshot( + pub fn get_incoming_recursive_references_with_snapshot( &self, id: I, snapshot: &TypeArchiveSnapshotId, ) -> Array { - let id = id.into_bytes_with_nul(); let mut count = 0; let result = unsafe { BNGetTypeArchiveIncomingRecursiveTypeReferences( self.handle.as_ptr(), - id.as_ref().as_ptr() as *const c_char, + id.as_cstr().as_ptr(), snapshot.0.as_ptr() as *const c_char, &mut count, ) @@ -596,11 +572,9 @@ impl TypeArchive { } /// Look up a metadata entry in the archive - pub fn query_metadata(&self, key: S) -> Option> { - let key = key.into_bytes_with_nul(); - let result = unsafe { - BNTypeArchiveQueryMetadata(self.handle.as_ptr(), key.as_ref().as_ptr() as *const c_char) - }; + pub fn query_metadata(&self, key: S) -> Option> { + let result = + unsafe { BNTypeArchiveQueryMetadata(self.handle.as_ptr(), key.as_cstr().as_ptr()) }; (!result.is_null()).then(|| unsafe { Metadata::ref_from_raw(result) }) } @@ -608,34 +582,20 @@ impl TypeArchive { /// /// * `key` - key value to associate the Metadata object with /// * `md` - object to store. - pub fn store_metadata(&self, key: S, md: &Metadata) { - let key = key.into_bytes_with_nul(); + pub fn store_metadata(&self, key: S, md: &Metadata) { let result = unsafe { - BNTypeArchiveStoreMetadata( - self.handle.as_ptr(), - key.as_ref().as_ptr() as *const c_char, - md.handle, - ) + BNTypeArchiveStoreMetadata(self.handle.as_ptr(), key.as_cstr().as_ptr(), md.handle) }; assert!(result); } /// Delete a given metadata entry in the archive from the `key` - pub fn remove_metadata(&self, key: S) -> bool { - let key = key.into_bytes_with_nul(); - unsafe { - BNTypeArchiveRemoveMetadata( - self.handle.as_ptr(), - key.as_ref().as_ptr() as *const c_char, - ) - } + pub fn remove_metadata(&self, key: S) -> bool { + unsafe { BNTypeArchiveRemoveMetadata(self.handle.as_ptr(), key.as_cstr().as_ptr()) } } /// Turn a given `snapshot` id into a data stream - pub fn serialize_snapshot( - &self, - snapshot: &TypeArchiveSnapshotId, - ) -> DataBuffer { + pub fn serialize_snapshot(&self, snapshot: &TypeArchiveSnapshotId) -> DataBuffer { let result = unsafe { BNTypeArchiveSerializeSnapshot( self.handle.as_ptr(), @@ -707,9 +667,8 @@ impl TypeArchive { // TODO: Make this AsRef? /// Determine if `file` is a Type Archive - pub fn is_type_archive(file: P) -> bool { - let file = file.into_bytes_with_nul(); - unsafe { BNIsTypeArchive(file.as_ref().as_ptr() as *const c_char) } + pub fn is_type_archive(file: P) -> bool { + unsafe { BNIsTypeArchive(file.as_cstr().as_ptr()) } } ///// Get the TypeContainer interface for this Type Archive, presenting types @@ -732,7 +691,7 @@ impl TypeArchive { parents: &[TypeArchiveSnapshotId], ) -> TypeArchiveSnapshotId where - P: BnStrCompatible, + P: AsCStr, F: FnMut(&TypeArchiveSnapshotId) -> bool, { unsafe extern "C" fn cb_callback bool>( @@ -779,12 +738,12 @@ impl TypeArchive { merge_conflicts: M, ) -> Result> where - B: BnStrCompatible, - F: BnStrCompatible, - S: BnStrCompatible, + B: AsCStr, + F: AsCStr, + S: AsCStr, M: IntoIterator, - MI: BnStrCompatible, - MK: BnStrCompatible, + MI: AsCStr, + MK: AsCStr, { self.merge_snapshots_with_progress( base_snapshot, @@ -814,16 +773,13 @@ impl TypeArchive { progress: impl Into, ) -> Result> where - B: BnStrCompatible, - F: BnStrCompatible, - S: BnStrCompatible, + B: AsCStr, + F: AsCStr, + S: AsCStr, M: IntoIterator, - MI: BnStrCompatible, - MK: BnStrCompatible, + MI: AsCStr, + MK: AsCStr, { - let base_snapshot = base_snapshot.into_bytes_with_nul(); - let first_snapshot = first_snapshot.into_bytes_with_nul(); - let second_snapshot = second_snapshot.into_bytes_with_nul(); let (merge_keys, merge_values): (Vec, Vec) = merge_conflicts .into_iter() .map(|(k, v)| (BnString::new(k), BnString::new(v))) @@ -841,9 +797,9 @@ impl TypeArchive { let success = unsafe { BNTypeArchiveMergeSnapshots( self.handle.as_ptr(), - base_snapshot.as_ref().as_ptr() as *const c_char, - first_snapshot.as_ref().as_ptr() as *const c_char, - second_snapshot.as_ref().as_ptr() as *const c_char, + base_snapshot.as_cstr().as_ptr(), + first_snapshot.as_cstr().as_ptr(), + second_snapshot.as_cstr().as_ptr(), merge_keys_raw, merge_values_raw, merge_keys.len(), diff --git a/rust/src/type_container.rs b/rust/src/type_container.rs index e060d87b9..df9b99a6b 100644 --- a/rust/src/type_container.rs +++ b/rust/src/type_container.rs @@ -11,12 +11,12 @@ use crate::platform::Platform; use crate::progress::ProgressExecutor; use crate::rc::{Array, Ref}; -use crate::string::{raw_to_string, BnStrCompatible, BnString}; +use crate::string::{raw_to_string, AsCStr, BnString}; use crate::type_parser::{TypeParserError, TypeParserResult}; use crate::types::{QualifiedName, QualifiedNameAndType, Type}; use binaryninjacore_sys::*; use std::collections::HashMap; -use std::ffi::{c_char, c_void}; +use std::ffi::c_void; use std::fmt::{Debug, Formatter}; use std::ptr::NonNull; @@ -142,19 +142,10 @@ impl TypeContainer { /// (by id) to use the new name. /// /// Returns true if the type was renamed. - pub fn rename_type, S: BnStrCompatible>( - &self, - name: T, - type_id: S, - ) -> bool { - let type_id = type_id.into_bytes_with_nul(); + pub fn rename_type, S: AsCStr>(&self, name: T, type_id: S) -> bool { let raw_name = QualifiedName::into_raw(name.into()); let success = unsafe { - BNTypeContainerRenameType( - self.handle.as_ptr(), - type_id.as_ref().as_ptr() as *const c_char, - &raw_name, - ) + BNTypeContainerRenameType(self.handle.as_ptr(), type_id.as_cstr().as_ptr(), &raw_name) }; QualifiedName::free_raw(raw_name); success @@ -164,14 +155,8 @@ impl TypeContainer { /// not specified and you may end up with broken references if any still exist. /// /// Returns true if the type was deleted. - pub fn delete_type(&self, type_id: S) -> bool { - let type_id = type_id.into_bytes_with_nul(); - unsafe { - BNTypeContainerDeleteType( - self.handle.as_ptr(), - type_id.as_ref().as_ptr() as *const c_char, - ) - } + pub fn delete_type(&self, type_id: S) -> bool { + unsafe { BNTypeContainerDeleteType(self.handle.as_ptr(), type_id.as_cstr().as_ptr()) } } /// Get the unique id of the type in the Type Container with the given name. @@ -189,13 +174,12 @@ impl TypeContainer { /// Get the unique name of the type in the Type Container with the given id. /// /// If no type with that id exists, returns None. - pub fn type_name(&self, type_id: S) -> Option { - let type_id = type_id.into_bytes_with_nul(); + pub fn type_name(&self, type_id: S) -> Option { let mut result = BNQualifiedName::default(); let success = unsafe { BNTypeContainerGetTypeName( self.handle.as_ptr(), - type_id.as_ref().as_ptr() as *const c_char, + type_id.as_cstr().as_ptr(), &mut result, ) }; @@ -205,13 +189,12 @@ impl TypeContainer { /// Get the definition of the type in the Type Container with the given id. /// /// If no type with that id exists, returns None. - pub fn type_by_id(&self, type_id: S) -> Option> { - let type_id = type_id.into_bytes_with_nul(); + pub fn type_by_id(&self, type_id: S) -> Option> { let mut result = std::ptr::null_mut(); let success = unsafe { BNTypeContainerGetTypeById( self.handle.as_ptr(), - type_id.as_ref().as_ptr() as *const c_char, + type_id.as_cstr().as_ptr(), &mut result, ) }; @@ -310,19 +293,18 @@ impl TypeContainer { /// /// * `source` - Source code to parse /// * `import_dependencies` - If Type Library / Type Archive types should be imported during parsing - pub fn parse_type_string( + pub fn parse_type_string( &self, source: S, import_dependencies: bool, ) -> Result> { - let source = source.into_bytes_with_nul(); let mut result = BNQualifiedNameAndType::default(); let mut errors = std::ptr::null_mut(); let mut error_count = 0; let success = unsafe { BNTypeContainerParseTypeString( self.handle.as_ptr(), - source.as_ref().as_ptr() as *const c_char, + source.as_cstr().as_ptr(), import_dependencies, &mut result, &mut errors, @@ -356,46 +338,41 @@ impl TypeContainer { import_dependencies: bool, ) -> Result> where - S: BnStrCompatible, - F: BnStrCompatible, + S: AsCStr, + F: AsCStr, O: IntoIterator, - O::Item: BnStrCompatible, + O::Item: AsCStr, D: IntoIterator, - D::Item: BnStrCompatible, - A: BnStrCompatible, + D::Item: AsCStr, + A: AsCStr, { - let source = source.into_bytes_with_nul(); - let filename = filename.into_bytes_with_nul(); - let options: Vec<_> = options - .into_iter() - .map(|o| o.into_bytes_with_nul()) - .collect(); - let options_raw: Vec<*const c_char> = options + let options = options.into_iter().collect::>(); + let options = options.iter().map(|o| o.as_cstr()).collect::>(); + let options_raw = options.iter().map(|o| o.as_ptr()).collect::>(); + + let include_directories = include_directories.into_iter().collect::>(); + let include_directories = include_directories .iter() - .map(|o| o.as_ref().as_ptr() as *const c_char) - .collect(); - let include_directories: Vec<_> = include_directories - .into_iter() - .map(|d| d.into_bytes_with_nul()) - .collect(); - let include_directories_raw: Vec<*const c_char> = include_directories + .map(|d| d.as_cstr()) + .collect::>(); + let include_directories_raw = include_directories .iter() - .map(|d| d.as_ref().as_ptr() as *const c_char) - .collect(); - let auto_type_source = auto_type_source.into_bytes_with_nul(); + .map(|d| d.as_ptr()) + .collect::>(); + let mut raw_result = BNTypeParserResult::default(); let mut errors = std::ptr::null_mut(); let mut error_count = 0; let success = unsafe { BNTypeContainerParseTypesFromSource( self.handle.as_ptr(), - source.as_ref().as_ptr() as *const c_char, - filename.as_ref().as_ptr() as *const c_char, + source.as_cstr().as_ptr(), + filename.as_cstr().as_ptr(), options_raw.as_ptr(), options_raw.len(), include_directories_raw.as_ptr(), include_directories_raw.len(), - auto_type_source.as_ref().as_ptr() as *const c_char, + auto_type_source.as_cstr().as_ptr(), import_dependencies, &mut raw_result, &mut errors, diff --git a/rust/src/type_library.rs b/rust/src/type_library.rs index ee978513e..08acd932c 100644 --- a/rust/src/type_library.rs +++ b/rust/src/type_library.rs @@ -1,13 +1,13 @@ use binaryninjacore_sys::*; -use core::{ffi, mem, ptr}; +use core::{mem, ptr}; use crate::{ architecture::CoreArchitecture, metadata::Metadata, platform::Platform, rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref}, - string::{BnStrCompatible, BnString}, + string::{AsCStr, BnString}, types::{QualifiedName, QualifiedNameAndType, Type}, }; @@ -42,10 +42,8 @@ impl TypeLibrary { } /// Creates an empty type library object with a random GUID and the provided name. - pub fn new(arch: CoreArchitecture, name: S) -> TypeLibrary { - let name = name.into_bytes_with_nul(); - let new_lib = - unsafe { BNNewTypeLibrary(arch.handle, name.as_ref().as_ptr() as *const ffi::c_char) }; + pub fn new(arch: CoreArchitecture, name: S) -> TypeLibrary { + let new_lib = unsafe { BNNewTypeLibrary(arch.handle, name.as_cstr().as_ptr()) }; unsafe { TypeLibrary::from_raw(ptr::NonNull::new(new_lib).unwrap()) } } @@ -57,49 +55,31 @@ impl TypeLibrary { } /// Decompresses a type library file to a file on disk. - pub fn decompress_to_file(path: P, output: O) -> bool { - let path = path.into_bytes_with_nul(); - let output = output.into_bytes_with_nul(); - unsafe { - BNTypeLibraryDecompressToFile( - path.as_ref().as_ptr() as *const ffi::c_char, - output.as_ref().as_ptr() as *const ffi::c_char, - ) - } + pub fn decompress_to_file(path: P, output: O) -> bool { + unsafe { BNTypeLibraryDecompressToFile(path.as_cstr().as_ptr(), output.as_cstr().as_ptr()) } } /// Loads a finalized type library instance from file - pub fn load_from_file(path: S) -> Option { - let path = path.into_bytes_with_nul(); - let handle = - unsafe { BNLoadTypeLibraryFromFile(path.as_ref().as_ptr() as *const ffi::c_char) }; + pub fn load_from_file(path: S) -> Option { + let handle = unsafe { BNLoadTypeLibraryFromFile(path.as_cstr().as_ptr()) }; ptr::NonNull::new(handle).map(|h| unsafe { TypeLibrary::from_raw(h) }) } /// Saves a finalized type library instance to file - pub fn write_to_file(&self, path: S) -> bool { - let path = path.into_bytes_with_nul(); - unsafe { - BNWriteTypeLibraryToFile(self.as_raw(), path.as_ref().as_ptr() as *const ffi::c_char) - } + pub fn write_to_file(&self, path: S) -> bool { + unsafe { BNWriteTypeLibraryToFile(self.as_raw(), path.as_cstr().as_ptr()) } } /// Looks up the first type library found with a matching name. Keep in mind that names are not /// necessarily unique. - pub fn from_name(arch: CoreArchitecture, name: S) -> Option { - let name = name.into_bytes_with_nul(); - let handle = unsafe { - BNLookupTypeLibraryByName(arch.handle, name.as_ref().as_ptr() as *const ffi::c_char) - }; + pub fn from_name(arch: CoreArchitecture, name: S) -> Option { + let handle = unsafe { BNLookupTypeLibraryByName(arch.handle, name.as_cstr().as_ptr()) }; ptr::NonNull::new(handle).map(|h| unsafe { TypeLibrary::from_raw(h) }) } /// Attempts to grab a type library associated with the provided Architecture and GUID pair - pub fn from_guid(arch: CoreArchitecture, guid: S) -> Option { - let guid = guid.into_bytes_with_nul(); - let handle = unsafe { - BNLookupTypeLibraryByGuid(arch.handle, guid.as_ref().as_ptr() as *const ffi::c_char) - }; + pub fn from_guid(arch: CoreArchitecture, guid: S) -> Option { + let handle = unsafe { BNLookupTypeLibraryByGuid(arch.handle, guid.as_cstr().as_ptr()) }; ptr::NonNull::new(handle).map(|h| unsafe { TypeLibrary::from_raw(h) }) } @@ -117,11 +97,8 @@ impl TypeLibrary { } /// Sets the name of a type library instance that has not been finalized - pub fn set_name(&self, value: S) { - let value = value.into_bytes_with_nul(); - unsafe { - BNSetTypeLibraryName(self.as_raw(), value.as_ref().as_ptr() as *const ffi::c_char) - } + pub fn set_name(&self, value: S) { + unsafe { BNSetTypeLibraryName(self.as_raw(), value.as_cstr().as_ptr()) } } /// The `dependency_name` of a library is the name used to record dependencies across @@ -135,14 +112,8 @@ impl TypeLibrary { } /// Sets the dependency name of a type library instance that has not been finalized - pub fn set_dependency_name(&self, value: S) { - let value = value.into_bytes_with_nul(); - unsafe { - BNSetTypeLibraryDependencyName( - self.as_raw(), - value.as_ref().as_ptr() as *const ffi::c_char, - ) - } + pub fn set_dependency_name(&self, value: S) { + unsafe { BNSetTypeLibraryDependencyName(self.as_raw(), value.as_cstr().as_ptr()) } } /// Returns the GUID associated with the type library @@ -152,11 +123,8 @@ impl TypeLibrary { } /// Sets the GUID of a type library instance that has not been finalized - pub fn set_guid(&self, value: S) { - let value = value.into_bytes_with_nul(); - unsafe { - BNSetTypeLibraryGuid(self.as_raw(), value.as_ref().as_ptr() as *const ffi::c_char) - } + pub fn set_guid(&self, value: S) { + unsafe { BNSetTypeLibraryGuid(self.as_raw(), value.as_cstr().as_ptr()) } } /// A list of extra names that will be considered a match by [Platform::get_type_libraries_by_name] @@ -168,14 +136,8 @@ impl TypeLibrary { } /// Adds an extra name to this type library used during library lookups and dependency resolution - pub fn add_alternate_name(&self, value: S) { - let value = value.into_bytes_with_nul(); - unsafe { - BNAddTypeLibraryAlternateName( - self.as_raw(), - value.as_ref().as_ptr() as *const ffi::c_char, - ) - } + pub fn add_alternate_name(&self, value: S) { + unsafe { BNAddTypeLibraryAlternateName(self.as_raw(), value.as_cstr().as_ptr()) } } /// Returns a list of all platform names that this type library will register with during platform @@ -212,11 +174,8 @@ impl TypeLibrary { } /// Retrieves a metadata associated with the given key stored in the type library - pub fn query_metadata(&self, key: S) -> Option { - let key = key.into_bytes_with_nul(); - let result = unsafe { - BNTypeLibraryQueryMetadata(self.as_raw(), key.as_ref().as_ptr() as *const ffi::c_char) - }; + pub fn query_metadata(&self, key: S) -> Option { + let result = unsafe { BNTypeLibraryQueryMetadata(self.as_raw(), key.as_cstr().as_ptr()) }; (!result.is_null()).then(|| unsafe { Metadata::from_raw(result) }) } @@ -231,23 +190,13 @@ impl TypeLibrary { /// /// * `key` - key value to associate the Metadata object with /// * `md` - object to store. - pub fn store_metadata(&self, key: S, md: &Metadata) { - let key = key.into_bytes_with_nul(); - unsafe { - BNTypeLibraryStoreMetadata( - self.as_raw(), - key.as_ref().as_ptr() as *const ffi::c_char, - md.handle, - ) - } + pub fn store_metadata(&self, key: S, md: &Metadata) { + unsafe { BNTypeLibraryStoreMetadata(self.as_raw(), key.as_cstr().as_ptr(), md.handle) } } /// Removes the metadata associated with key from the current type library. - pub fn remove_metadata(&self, key: S) { - let key = key.into_bytes_with_nul(); - unsafe { - BNTypeLibraryRemoveMetadata(self.as_raw(), key.as_ref().as_ptr() as *const ffi::c_char) - } + pub fn remove_metadata(&self, key: S) { + unsafe { BNTypeLibraryRemoveMetadata(self.as_raw(), key.as_cstr().as_ptr()) } } /// Retrieves the metadata associated with the current type library. @@ -299,15 +248,10 @@ impl TypeLibrary { /// Use this api with extreme caution. /// /// - pub fn add_type_source(&self, name: QualifiedName, source: S) { - let source = source.into_bytes_with_nul(); + pub fn add_type_source(&self, name: QualifiedName, source: S) { let mut raw_name = QualifiedName::into_raw(name); unsafe { - BNAddTypeLibraryNamedTypeSource( - self.as_raw(), - &mut raw_name, - source.as_ref().as_ptr() as *const ffi::c_char, - ) + BNAddTypeLibraryNamedTypeSource(self.as_raw(), &mut raw_name, source.as_cstr().as_ptr()) } QualifiedName::free_raw(raw_name); } diff --git a/rust/src/type_parser.rs b/rust/src/type_parser.rs index 656f0c9d4..259c667a5 100644 --- a/rust/src/type_parser.rs +++ b/rust/src/type_parser.rs @@ -6,7 +6,7 @@ use std::ptr::NonNull; use crate::platform::Platform; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref}; -use crate::string::{raw_to_string, BnStrCompatible, BnString}; +use crate::string::{raw_to_string, AsCStr, BnString}; use crate::type_container::TypeContainer; use crate::types::{QualifiedName, QualifiedNameAndType, Type}; @@ -14,7 +14,7 @@ pub type TypeParserErrorSeverity = BNTypeParserErrorSeverity; pub type TypeParserOption = BNTypeParserOption; /// Register a custom parser with the API -pub fn register_type_parser( +pub fn register_type_parser( name: S, parser: T, ) -> (&'static mut T, CoreTypeParser) { @@ -29,12 +29,7 @@ pub fn register_type_parser( freeResult: Some(cb_free_result), freeErrorList: Some(cb_free_error_list), }; - let result = unsafe { - BNRegisterTypeParser( - name.into_bytes_with_nul().as_ref().as_ptr() as *const _, - &mut callback, - ) - }; + let result = unsafe { BNRegisterTypeParser(name.as_cstr().as_ptr(), &mut callback) }; let core = unsafe { CoreTypeParser::from_raw(NonNull::new(result).unwrap()) }; (parser, core) } @@ -55,9 +50,8 @@ impl CoreTypeParser { unsafe { Array::new(result, count, ()) } } - pub fn parser_by_name(name: S) -> Option { - let name_raw = name.into_bytes_with_nul(); - let result = unsafe { BNGetTypeParserByName(name_raw.as_ref().as_ptr() as *const c_char) }; + pub fn parser_by_name(name: S) -> Option { + let result = unsafe { BNGetTypeParserByName(name.as_cstr().as_ptr()) }; NonNull::new(result).map(|x| unsafe { Self::from_raw(x) }) } @@ -71,18 +65,17 @@ impl CoreTypeParser { impl TypeParser for CoreTypeParser { fn get_option_text(&self, option: TypeParserOption, value: &str) -> Option { let mut output = std::ptr::null_mut(); - let value_cstr = BnString::new(value); let result = unsafe { BNGetTypeParserOptionText( self.handle.as_ptr(), option, - value_cstr.as_ptr(), + value.as_cstr().as_ptr(), &mut output, ) }; result.then(|| { assert!(!output.is_null()); - value_cstr.to_string() + value.to_string() }) } @@ -95,16 +88,14 @@ impl TypeParser for CoreTypeParser { options: &[String], include_dirs: &[String], ) -> Result> { - let source_cstr = BnString::new(source); - let file_name_cstr = BnString::new(file_name); let mut result = std::ptr::null_mut(); let mut errors = std::ptr::null_mut(); let mut error_count = 0; let success = unsafe { BNTypeParserPreprocessSource( self.handle.as_ptr(), - source_cstr.as_ptr(), - file_name_cstr.as_ptr(), + source.as_cstr().as_ptr(), + file_name.as_cstr().as_ptr(), platform.handle, existing_types.handle.as_ptr(), options.as_ptr() as *const *const c_char, @@ -136,24 +127,21 @@ impl TypeParser for CoreTypeParser { include_dirs: &[String], auto_type_source: &str, ) -> Result> { - let source_cstr = BnString::new(source); - let file_name_cstr = BnString::new(file_name); - let auto_type_source = BnString::new(auto_type_source); let mut raw_result = BNTypeParserResult::default(); let mut errors = std::ptr::null_mut(); let mut error_count = 0; let success = unsafe { BNTypeParserParseTypesFromSource( self.handle.as_ptr(), - source_cstr.as_ptr(), - file_name_cstr.as_ptr(), + source.as_cstr().as_ptr(), + file_name.as_cstr().as_ptr(), platform.handle, existing_types.handle.as_ptr(), options.as_ptr() as *const *const c_char, options.len(), include_dirs.as_ptr() as *const *const c_char, include_dirs.len(), - auto_type_source.as_ptr(), + auto_type_source.as_cstr().as_ptr(), &mut raw_result, &mut errors, &mut error_count, @@ -176,14 +164,13 @@ impl TypeParser for CoreTypeParser { platform: &Platform, existing_types: &TypeContainer, ) -> Result> { - let source_cstr = BnString::new(source); let mut output = BNQualifiedNameAndType::default(); let mut errors = std::ptr::null_mut(); let mut error_count = 0; let result = unsafe { BNTypeParserParseTypeString( self.handle.as_ptr(), - source_cstr.as_ptr(), + source.as_cstr().as_ptr(), platform.handle, existing_types.handle.as_ptr(), &mut output, diff --git a/rust/src/type_printer.rs b/rust/src/type_printer.rs index 12c716458..7a3d513f6 100644 --- a/rust/src/type_printer.rs +++ b/rust/src/type_printer.rs @@ -4,7 +4,7 @@ use crate::binary_view::BinaryView; use crate::disassembly::InstructionTextToken; use crate::platform::Platform; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref}; -use crate::string::{raw_to_string, BnStrCompatible, BnString}; +use crate::string::{raw_to_string, AsCStr, BnString}; use crate::type_container::TypeContainer; use crate::types::{NamedTypeReference, QualifiedName, QualifiedNameAndType, Type}; use binaryninjacore_sys::*; @@ -15,7 +15,7 @@ pub type TokenEscapingType = BNTokenEscapingType; pub type TypeDefinitionLineType = BNTypeDefinitionLineType; /// Register a custom parser with the API -pub fn register_type_printer( +pub fn register_type_printer( name: S, parser: T, ) -> (&'static mut T, CoreTypePrinter) { @@ -34,12 +34,7 @@ pub fn register_type_printer( freeString: Some(cb_free_string), freeLines: Some(cb_free_lines), }; - let result = unsafe { - BNRegisterTypePrinter( - name.into_bytes_with_nul().as_ref().as_ptr() as *const c_char, - &mut callback, - ) - }; + let result = unsafe { BNRegisterTypePrinter(name.as_cstr().as_ptr(), &mut callback) }; let core = unsafe { CoreTypePrinter::from_raw(NonNull::new(result).unwrap()) }; (parser, core) } @@ -61,9 +56,8 @@ impl CoreTypePrinter { unsafe { Array::new(result, count, ()) } } - pub fn printer_by_name(name: S) -> Option { - let name_raw = name.into_bytes_with_nul(); - let result = unsafe { BNGetTypePrinterByName(name_raw.as_ref().as_ptr() as *const c_char) }; + pub fn printer_by_name(name: S) -> Option { + let result = unsafe { BNGetTypePrinterByName(name.as_cstr().as_ptr()) }; NonNull::new(result).map(|x| unsafe { Self::from_raw(x) }) } diff --git a/rust/src/types.rs b/rust/src/types.rs index e7f2eb019..8c5ed0940 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -24,7 +24,7 @@ use crate::{ binary_view::{BinaryView, BinaryViewExt}, calling_convention::CallingConvention, rc::*, - string::{BnStrCompatible, BnString}, + string::{AsCStr, BnString}, }; use crate::confidence::{Conf, MAX_CONFIDENCE, MIN_CONFIDENCE}; @@ -253,44 +253,29 @@ impl TypeBuilder { Self::from_raw(BNCreateIntegerTypeBuilder( width, &mut is_signed, - BnString::new("").as_ptr() as *mut _, + BnString::new("").as_ptr(), )) } } - pub fn named_int(width: usize, is_signed: bool, alt_name: S) -> Self { + pub fn named_int(width: usize, is_signed: bool, alt_name: S) -> Self { let mut is_signed = Conf::new(is_signed, MAX_CONFIDENCE).into(); - // let alt_name = BnString::new(alt_name); - let alt_name = alt_name.into_bytes_with_nul(); // This segfaulted once, so the above version is there if we need to change to it, but in theory this is copied into a `const string&` on the C++ side; I'm just not 100% confident that a constant reference copies data unsafe { Self::from_raw(BNCreateIntegerTypeBuilder( width, &mut is_signed, - alt_name.as_ref().as_ptr() as _, + alt_name.as_cstr().as_ptr(), )) } } pub fn float(width: usize) -> Self { - unsafe { - Self::from_raw(BNCreateFloatTypeBuilder( - width, - BnString::new("").as_ptr() as *mut _, - )) - } + unsafe { Self::from_raw(BNCreateFloatTypeBuilder(width, BnString::new("").as_ptr())) } } - pub fn named_float(width: usize, alt_name: S) -> Self { - // let alt_name = BnString::new(alt_name); - let alt_name = alt_name.into_bytes_with_nul(); // See same line in `named_int` above - - unsafe { - Self::from_raw(BNCreateFloatTypeBuilder( - width, - alt_name.as_ref().as_ptr() as _, - )) - } + pub fn named_float(width: usize, alt_name: S) -> Self { + unsafe { Self::from_raw(BNCreateFloatTypeBuilder(width, alt_name.as_cstr().as_ptr())) } } pub fn array<'a, T: Into>>(ty: T, count: u64) -> Self { @@ -630,12 +615,7 @@ impl Type { } pub fn wide_char(width: usize) -> Ref { - unsafe { - Self::ref_from_raw(BNCreateWideCharType( - width, - BnString::new("").as_ptr() as *mut _, - )) - } + unsafe { Self::ref_from_raw(BNCreateWideCharType(width, BnString::new("").as_ptr())) } } pub fn int(width: usize, is_signed: bool) -> Ref { @@ -644,39 +624,29 @@ impl Type { Self::ref_from_raw(BNCreateIntegerType( width, &mut is_signed, - BnString::new("").as_ptr() as *mut _, + BnString::new("").as_ptr(), )) } } - pub fn named_int(width: usize, is_signed: bool, alt_name: S) -> Ref { + pub fn named_int(width: usize, is_signed: bool, alt_name: S) -> Ref { let mut is_signed = Conf::new(is_signed, MAX_CONFIDENCE).into(); - // let alt_name = BnString::new(alt_name); - let alt_name = alt_name.into_bytes_with_nul(); // This segfaulted once, so the above version is there if we need to change to it, but in theory this is copied into a `const string&` on the C++ side; I'm just not 100% confident that a constant reference copies data unsafe { Self::ref_from_raw(BNCreateIntegerType( width, &mut is_signed, - alt_name.as_ref().as_ptr() as _, + alt_name.as_cstr().as_ptr(), )) } } pub fn float(width: usize) -> Ref { - unsafe { - Self::ref_from_raw(BNCreateFloatType( - width, - BnString::new("").as_ptr() as *mut _, - )) - } + unsafe { Self::ref_from_raw(BNCreateFloatType(width, BnString::new("").as_ptr())) } } - pub fn named_float(width: usize, alt_name: S) -> Ref { - // let alt_name = BnString::new(alt_name); - let alt_name = alt_name.into_bytes_with_nul(); // See same line in `named_int` above - - unsafe { Self::ref_from_raw(BNCreateFloatType(width, alt_name.as_ref().as_ptr() as _)) } + pub fn named_float(width: usize, alt_name: S) -> Ref { + unsafe { Self::ref_from_raw(BNCreateFloatType(width, alt_name.as_cstr().as_ptr())) } } pub fn array<'a, T: Into>>(ty: T, count: u64) -> Ref { @@ -1218,26 +1188,21 @@ impl EnumerationBuilder { unsafe { Enumeration::ref_from_raw(BNFinalizeEnumerationBuilder(self.handle)) } } - pub fn append(&self, name: S) -> &Self { - let name = name.into_bytes_with_nul(); - unsafe { - BNAddEnumerationBuilderMember(self.handle, name.as_ref().as_ptr() as _); - } + pub fn append(&self, name: S) -> &Self { + unsafe { BNAddEnumerationBuilderMember(self.handle, name.as_cstr().as_ptr()) } self } - pub fn insert(&self, name: S, value: u64) -> &Self { - let name = name.into_bytes_with_nul(); + pub fn insert(&self, name: S, value: u64) -> &Self { unsafe { - BNAddEnumerationBuilderMemberWithValue(self.handle, name.as_ref().as_ptr() as _, value); + BNAddEnumerationBuilderMemberWithValue(self.handle, name.as_cstr().as_ptr(), value) } self } - pub fn replace(&self, id: usize, name: S, value: u64) -> &Self { - let name = name.into_bytes_with_nul(); + pub fn replace(&self, id: usize, name: S, value: u64) -> &Self { unsafe { - BNReplaceEnumerationBuilderMember(self.handle, id, name.as_ref().as_ptr() as _, value); + BNReplaceEnumerationBuilderMember(self.handle, id, name.as_cstr().as_ptr(), value) } self } @@ -1477,20 +1442,19 @@ impl StructureBuilder { self } - pub fn append<'a, S: BnStrCompatible, T: Into>>( + pub fn append<'a, S: AsCStr, T: Into>>( &mut self, ty: T, name: S, access: MemberAccess, scope: MemberScope, ) -> &mut Self { - let name = name.into_bytes_with_nul(); let owned_raw_ty = Conf::<&Type>::into_raw(ty.into()); unsafe { BNAddStructureBuilderMember( self.handle, &owned_raw_ty, - name.as_ref().as_ptr() as _, + name.as_cstr().as_ptr(), access, scope, ); @@ -1514,7 +1478,7 @@ impl StructureBuilder { self } - pub fn insert<'a, S: BnStrCompatible, T: Into>>( + pub fn insert<'a, S: AsCStr, T: Into>>( &mut self, ty: T, name: S, @@ -1523,13 +1487,12 @@ impl StructureBuilder { access: MemberAccess, scope: MemberScope, ) -> &mut Self { - let name = name.into_bytes_with_nul(); let owned_raw_ty = Conf::<&Type>::into_raw(ty.into()); unsafe { BNAddStructureBuilderMemberAtOffset( self.handle, &owned_raw_ty, - name.as_ref().as_ptr() as _, + name.as_cstr().as_ptr(), offset, overwrite_existing, access, @@ -1539,21 +1502,20 @@ impl StructureBuilder { self } - pub fn replace<'a, S: BnStrCompatible, T: Into>>( + pub fn replace<'a, S: AsCStr, T: Into>>( &mut self, index: usize, ty: T, name: S, overwrite_existing: bool, ) -> &mut Self { - let name = name.into_bytes_with_nul(); let owned_raw_ty = Conf::<&Type>::into_raw(ty.into()); unsafe { BNReplaceStructureBuilderMember( self.handle, index, &owned_raw_ty, - name.as_ref().as_ptr() as _, + name.as_cstr().as_ptr(), overwrite_existing, ) } @@ -1863,17 +1825,16 @@ impl NamedTypeReference { /// You should not assign type ids yourself: if you use this to reference a type you are going /// to create but have not yet created, you may run into problems when giving your types to /// a BinaryView. - pub fn new_with_id, S: BnStrCompatible>( + pub fn new_with_id, S: AsCStr>( type_class: NamedTypeReferenceClass, type_id: S, name: T, ) -> Ref { - let type_id = type_id.into_bytes_with_nul(); let mut raw_name = QualifiedName::into_raw(name.into()); let result = unsafe { Self::ref_from_raw(BNCreateNamedType( type_class, - type_id.as_ref().as_ptr() as _, + type_id.as_cstr().as_ptr(), &mut raw_name, )) }; diff --git a/rust/src/worker_thread.rs b/rust/src/worker_thread.rs index 349456e5f..91caef17a 100644 --- a/rust/src/worker_thread.rs +++ b/rust/src/worker_thread.rs @@ -1,6 +1,6 @@ -use crate::string::BnStrCompatible; +use crate::string::AsCStr; use binaryninjacore_sys::*; -use std::ffi::{c_char, c_void}; +use std::ffi::c_void; pub struct WorkerThreadActionExecutor { func: Box, @@ -17,41 +17,38 @@ impl WorkerThreadActionExecutor { } } -pub fn execute_on_worker_thread(name: S, f: F) { +pub fn execute_on_worker_thread(name: S, f: F) { let boxed_executor = Box::new(WorkerThreadActionExecutor { func: Box::new(f) }); let raw_executor = Box::into_raw(boxed_executor); - let name = name.into_bytes_with_nul(); unsafe { BNWorkerEnqueueNamed( raw_executor as *mut c_void, Some(WorkerThreadActionExecutor::cb_execute), - name.as_ref().as_ptr() as *const c_char, + name.as_cstr().as_ptr(), ) } } -pub fn execute_on_worker_thread_priority(name: S, f: F) { +pub fn execute_on_worker_thread_priority(name: S, f: F) { let boxed_executor = Box::new(WorkerThreadActionExecutor { func: Box::new(f) }); let raw_executor = Box::into_raw(boxed_executor); - let name = name.into_bytes_with_nul(); unsafe { BNWorkerPriorityEnqueueNamed( raw_executor as *mut c_void, Some(WorkerThreadActionExecutor::cb_execute), - name.as_ref().as_ptr() as *const c_char, + name.as_cstr().as_ptr(), ) } } -pub fn execute_on_worker_thread_interactive(name: S, f: F) { +pub fn execute_on_worker_thread_interactive(name: S, f: F) { let boxed_executor = Box::new(WorkerThreadActionExecutor { func: Box::new(f) }); let raw_executor = Box::into_raw(boxed_executor); - let name = name.into_bytes_with_nul(); unsafe { BNWorkerInteractiveEnqueueNamed( raw_executor as *mut c_void, Some(WorkerThreadActionExecutor::cb_execute), - name.as_ref().as_ptr() as *const c_char, + name.as_cstr().as_ptr(), ) } } diff --git a/rust/src/workflow.rs b/rust/src/workflow.rs index 68cd3e18d..2a8843951 100644 --- a/rust/src/workflow.rs +++ b/rust/src/workflow.rs @@ -12,7 +12,7 @@ use crate::low_level_il::function::{LowLevelILFunction, Mutable, NonSSA, NonSSAV use crate::low_level_il::MutableLiftedILFunction; use crate::medium_level_il::MediumLevelILFunction; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; #[repr(transparent)] /// The AnalysisContext struct is used to represent the current state of @@ -115,14 +115,8 @@ impl AnalysisContext { } } - pub fn inform(&self, request: S) -> bool { - let request = request.into_bytes_with_nul(); - unsafe { - BNAnalysisContextInform( - self.handle.as_ptr(), - request.as_ref().as_ptr() as *const c_char, - ) - } + pub fn inform(&self, request: S) -> bool { + unsafe { BNAnalysisContextInform(self.handle.as_ptr(), request.as_cstr().as_ptr()) } } pub fn set_basic_blocks(&self, blocks: I) @@ -173,12 +167,11 @@ impl Activity { Ref::new(Self { handle }) } - pub fn new(config: S) -> Self { + pub fn new(config: S) -> Self { unsafe extern "C" fn cb_action_nop(_: *mut c_void, _: *mut BNAnalysisContext) {} - let config = config.into_bytes_with_nul(); let result = unsafe { BNCreateActivity( - config.as_ref().as_ptr() as *const c_char, + config.as_cstr().as_ptr(), std::ptr::null_mut(), Some(cb_action_nop), ) @@ -188,7 +181,7 @@ impl Activity { pub fn new_with_action(config: S, mut action: F) -> Self where - S: BnStrCompatible, + S: AsCStr, F: FnMut(&AnalysisContext), { unsafe extern "C" fn cb_action( @@ -200,10 +193,9 @@ impl Activity { ctxt(&AnalysisContext::from_raw(analysis)) } } - let config = config.into_bytes_with_nul(); let result = unsafe { BNCreateActivity( - config.as_ref().as_ptr() as *const c_char, + config.as_cstr().as_ptr(), &mut action as *mut F as *mut c_void, Some(cb_action::), ) @@ -257,9 +249,8 @@ impl Workflow { /// Create a new unregistered [Workflow] with no activities. /// /// To get a copy of an existing registered [Workflow] use [Workflow::clone]. - pub fn new(name: S) -> Self { - let name = name.into_bytes_with_nul(); - let result = unsafe { BNCreateWorkflow(name.as_ref().as_ptr() as *const c_char) }; + pub fn new(name: S) -> Self { + let result = unsafe { BNCreateWorkflow(name.as_cstr().as_ptr()) }; unsafe { Workflow::from_raw(NonNull::new(result).unwrap()) } } @@ -267,7 +258,7 @@ impl Workflow { /// /// * `name` - the name for the new [Workflow] #[must_use] - pub fn clone(&self, name: S) -> Workflow { + pub fn clone(&self, name: S) -> Workflow { self.clone_with_root(name, "") } @@ -276,29 +267,21 @@ impl Workflow { /// * `name` - the name for the new [Workflow] /// * `root_activity` - perform the clone operation with this activity as the root #[must_use] - pub fn clone_with_root( - &self, - name: S, - root_activity: A, - ) -> Workflow { - let raw_name = name.into_bytes_with_nul(); - let activity = root_activity.into_bytes_with_nul(); + pub fn clone_with_root(&self, name: S, root_activity: A) -> Workflow { unsafe { Self::from_raw( NonNull::new(BNWorkflowClone( self.handle.as_ptr(), - raw_name.as_ref().as_ptr() as *const c_char, - activity.as_ref().as_ptr() as *const c_char, + name.as_cstr().as_ptr(), + root_activity.as_cstr().as_ptr(), )) .unwrap(), ) } } - pub fn instance(name: S) -> Workflow { - let result = unsafe { - BNWorkflowInstance(name.into_bytes_with_nul().as_ref().as_ptr() as *const c_char) - }; + pub fn instance(name: S) -> Workflow { + let result = unsafe { BNWorkflowInstance(name.as_cstr().as_ptr()) }; unsafe { Workflow::from_raw(NonNull::new(result).unwrap()) } } @@ -324,14 +307,8 @@ impl Workflow { /// Register this [Workflow], making it immutable and available for use. /// /// * `configuration` - a JSON representation of the workflow configuration - pub fn register_with_config(&self, config: S) -> Result<(), ()> { - let config = config.into_bytes_with_nul(); - if unsafe { - BNRegisterWorkflow( - self.handle.as_ptr(), - config.as_ref().as_ptr() as *const c_char, - ) - } { + pub fn register_with_config(&self, config: S) -> Result<(), ()> { + if unsafe { BNRegisterWorkflow(self.handle.as_ptr(), config.as_cstr().as_ptr()) } { Ok(()) } else { Err(()) @@ -356,16 +333,11 @@ impl Workflow { ) -> Result where I: IntoIterator, - I::Item: BnStrCompatible, + I::Item: AsCStr, { - let subactivities_raw: Vec<_> = subactivities - .into_iter() - .map(|x| x.into_bytes_with_nul()) - .collect(); - let mut subactivities_ptr: Vec<*const _> = subactivities_raw - .iter() - .map(|x| x.as_ref().as_ptr() as *const c_char) - .collect(); + let subactivities = subactivities.into_iter().collect::>(); + let subactivities_raw: Vec<_> = subactivities.iter().map(|x| x.as_cstr()).collect(); + let mut subactivities_ptr: Vec<_> = subactivities_raw.iter().map(|x| x.as_ptr()).collect(); let result = unsafe { BNWorkflowRegisterActivity( self.handle.as_ptr(), @@ -379,13 +351,8 @@ impl Workflow { } /// Determine if an Activity exists in this [Workflow]. - pub fn contains(&self, activity: A) -> bool { - unsafe { - BNWorkflowContains( - self.handle.as_ptr(), - activity.into_bytes_with_nul().as_ref().as_ptr() as *const c_char, - ) - } + pub fn contains(&self, activity: A) -> bool { + unsafe { BNWorkflowContains(self.handle.as_ptr(), activity.as_cstr().as_ptr()) } } /// Retrieve the configuration as an adjacency list in JSON for the [Workflow]. @@ -397,12 +364,9 @@ impl Workflow { /// [Workflow], just for the given `activity`. /// /// `activity` - return the configuration for the `activity` - pub fn configuration_with_activity(&self, activity: A) -> BnString { + pub fn configuration_with_activity(&self, activity: A) -> BnString { let result = unsafe { - BNWorkflowGetConfiguration( - self.handle.as_ptr(), - activity.into_bytes_with_nul().as_ref().as_ptr() as *const c_char, - ) + BNWorkflowGetConfiguration(self.handle.as_ptr(), activity.as_cstr().as_ptr()) }; assert!(!result.is_null()); unsafe { BnString::from_raw(result) } @@ -418,14 +382,9 @@ impl Workflow { } /// Retrieve the Activity object for the specified `name`. - pub fn activity(&self, name: A) -> Option { - let name = name.into_bytes_with_nul(); - let result = unsafe { - BNWorkflowGetActivity( - self.handle.as_ptr(), - name.as_ref().as_ptr() as *const c_char, - ) - }; + pub fn activity(&self, name: A) -> Option { + let result = + unsafe { BNWorkflowGetActivity(self.handle.as_ptr(), name.as_cstr().as_ptr()) }; NonNull::new(result).map(|a| unsafe { Activity::from_raw(a) }) } @@ -433,12 +392,12 @@ impl Workflow { /// specified just for the given `activity`. /// /// * `activity` - if specified, return the roots for the `activity` - pub fn activity_roots(&self, activity: A) -> Array { + pub fn activity_roots(&self, activity: A) -> Array { let mut count = 0; let result = unsafe { BNWorkflowGetActivityRoots( self.handle.as_ptr(), - activity.into_bytes_with_nul().as_ref().as_ptr() as *const c_char, + activity.as_cstr().as_ptr(), &mut count, ) }; @@ -450,16 +409,12 @@ impl Workflow { /// /// * `activity` - if specified, return the direct children and optionally the descendants of the `activity` (includes `activity`) /// * `immediate` - whether to include only direct children of `activity` or all descendants - pub fn subactivities( - &self, - activity: A, - immediate: bool, - ) -> Array { + pub fn subactivities(&self, activity: A, immediate: bool) -> Array { let mut count = 0; let result = unsafe { BNWorkflowGetSubactivities( self.handle.as_ptr(), - activity.into_bytes_with_nul().as_ref().as_ptr() as *const c_char, + activity.as_cstr().as_ptr(), immediate, &mut count, ) @@ -474,22 +429,17 @@ impl Workflow { /// * `activities` - the list of Activities to assign pub fn assign_subactivities(&self, activity: A, activities: I) -> bool where - A: BnStrCompatible, + A: AsCStr, I: IntoIterator, - I::Item: BnStrCompatible, + I::Item: AsCStr, { - let input_list: Vec<_> = activities - .into_iter() - .map(|a| a.into_bytes_with_nul()) - .collect(); - let mut input_list_ptr: Vec<*const _> = input_list - .iter() - .map(|x| x.as_ref().as_ptr() as *const c_char) - .collect(); + let activities = activities.into_iter().collect::>(); + let input_list: Vec<_> = activities.iter().map(|a| a.as_cstr()).collect(); + let mut input_list_ptr: Vec<_> = input_list.iter().map(|x| x.as_ptr()).collect(); unsafe { BNWorkflowAssignSubactivities( self.handle.as_ptr(), - activity.into_bytes_with_nul().as_ref().as_ptr() as *const c_char, + activity.as_cstr().as_ptr(), input_list_ptr.as_mut_ptr(), input_list.len(), ) @@ -507,22 +457,17 @@ impl Workflow { /// * `activities` - the list of Activities to insert pub fn insert(&self, activity: A, activities: I) -> bool where - A: BnStrCompatible, + A: AsCStr, I: IntoIterator, - I::Item: BnStrCompatible, + I::Item: AsCStr, { - let input_list: Vec<_> = activities - .into_iter() - .map(|a| a.into_bytes_with_nul()) - .collect(); - let mut input_list_ptr: Vec<*const _> = input_list - .iter() - .map(|x| x.as_ref().as_ptr() as *const c_char) - .collect(); + let activities = activities.into_iter().collect::>(); + let input_list: Vec<_> = activities.iter().map(|a| a.as_cstr()).collect(); + let mut input_list_ptr: Vec<*const _> = input_list.iter().map(|x| x.as_ptr()).collect(); unsafe { BNWorkflowInsert( self.handle.as_ptr(), - activity.into_bytes_with_nul().as_ref().as_ptr() as *const c_char, + activity.as_cstr().as_ptr(), input_list_ptr.as_mut_ptr(), input_list.len(), ) @@ -530,29 +475,20 @@ impl Workflow { } /// Remove the specified `activity` - pub fn remove(&self, activity: A) -> bool { - unsafe { - BNWorkflowRemove( - self.handle.as_ptr(), - activity.into_bytes_with_nul().as_ref().as_ptr() as *const c_char, - ) - } + pub fn remove(&self, activity: A) -> bool { + unsafe { BNWorkflowRemove(self.handle.as_ptr(), activity.as_cstr().as_ptr()) } } /// Replace the specified `activity`. /// /// * `activity` - the Activity to replace /// * `new_activity` - the replacement Activity - pub fn replace( - &self, - activity: A, - new_activity: N, - ) -> bool { + pub fn replace(&self, activity: A, new_activity: N) -> bool { unsafe { BNWorkflowReplace( self.handle.as_ptr(), - activity.into_bytes_with_nul().as_ref().as_ptr() as *const c_char, - new_activity.into_bytes_with_nul().as_ref().as_ptr() as *const c_char, + activity.as_cstr().as_ptr(), + new_activity.as_cstr().as_ptr(), ) } } @@ -561,17 +497,12 @@ impl Workflow { /// /// * `activity` - if specified, generate the Flowgraph using `activity` as the root /// * `sequential` - whether to generate a **Composite** or **Sequential** style graph - pub fn graph( - &self, - activity: A, - sequential: Option, - ) -> Option { + pub fn graph(&self, activity: A, sequential: Option) -> Option { let sequential = sequential.unwrap_or(false); - let activity_name = activity.into_bytes_with_nul(); let graph = unsafe { BNWorkflowGetGraph( self.handle.as_ptr(), - activity_name.as_ref().as_ptr() as *const c_char, + activity.as_cstr().as_ptr(), sequential, ) };