From 926681db780c26165ed489fb6443737247d1a145 Mon Sep 17 00:00:00 2001 From: Michael Krasnitski Date: Mon, 20 Jan 2025 21:16:50 -0500 Subject: [PATCH] Replace `BnStrCompatible` with `AsCStr` trait --- plugins/warp/src/matcher.rs | 2 +- rust/src/architecture.rs | 20 +- rust/src/background_task.rs | 12 +- rust/src/binary_view.rs | 218 +++++++------------- rust/src/binary_view/memory_map.rs | 119 +++-------- rust/src/calling_convention.rs | 7 +- rust/src/collaboration.rs | 73 +++---- rust/src/collaboration/changeset.rs | 13 +- rust/src/collaboration/file.rs | 77 +++----- rust/src/collaboration/folder.rs | 22 +-- rust/src/collaboration/group.rs | 34 +--- rust/src/collaboration/merge.rs | 32 +-- rust/src/collaboration/project.rs | 210 +++++++------------- rust/src/collaboration/remote.rs | 204 +++++++------------ rust/src/collaboration/snapshot.rs | 9 +- rust/src/collaboration/sync.rs | 44 ++--- rust/src/collaboration/user.rs | 22 +-- rust/src/command.rs | 50 ++--- rust/src/component.rs | 51 ++--- rust/src/custom_binary_view.rs | 19 +- rust/src/data_buffer.rs | 4 +- rust/src/database.rs | 54 +++-- rust/src/database/kvs.rs | 24 +-- rust/src/database/snapshot.rs | 10 +- rust/src/debuginfo.rs | 286 +++++++++------------------ rust/src/demangle.rs | 49 ++--- rust/src/disassembly.rs | 13 +- rust/src/download_provider.rs | 43 ++-- rust/src/enterprise.rs | 26 +-- rust/src/external_library.rs | 9 +- rust/src/file_metadata.rs | 70 +++---- rust/src/function.rs | 28 +-- rust/src/high_level_il/operation.rs | 14 +- rust/src/interaction.rs | 103 ++++------ rust/src/lib.rs | 77 +++----- rust/src/medium_level_il/function.rs | 25 +-- rust/src/metadata.rs | 89 +++------ rust/src/platform.rs | 64 ++---- rust/src/project.rs | 211 +++++++------------- rust/src/project/file.rs | 33 +--- rust/src/project/folder.rs | 32 +-- rust/src/relocation.rs | 8 +- rust/src/render_layer.rs | 17 +- rust/src/repository.rs | 13 +- rust/src/repository/manager.rs | 29 +-- rust/src/secrets_provider.rs | 44 ++--- rust/src/section.rs | 54 ++--- rust/src/settings.rs | 266 ++++++++----------------- rust/src/string.rs | 187 ++++++++---------- rust/src/symbol.rs | 75 ++----- rust/src/tags.rs | 39 ++-- rust/src/template_simplifier.rs | 15 +- rust/src/type_archive.rs | 178 ++++++----------- rust/src/type_container.rs | 87 +++----- rust/src/type_library.rs | 116 +++-------- rust/src/type_parser.rs | 39 ++-- rust/src/type_printer.rs | 16 +- rust/src/types.rs | 95 +++------ rust/src/websocket/client.rs | 39 ++-- rust/src/websocket/provider.rs | 13 +- rust/src/worker_thread.rs | 19 +- rust/src/workflow.rs | 184 ++++++----------- rust/tests/websocket.rs | 6 +- 63 files changed, 1325 insertions(+), 2716 deletions(-) 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 41395e0d9..b99cadd81 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, @@ -1945,11 +1944,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()), @@ -2025,7 +2022,7 @@ pub trait ArchitectureExt: Architecture { fn register_relocation_handler(&self, name: S, func: F) where - S: BnStrCompatible, + S: AsCStr, R: 'static + RelocationHandler> + Send @@ -2048,7 +2045,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, { @@ -3134,8 +3131,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), @@ -3225,8 +3220,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 aa7c65e60..51277c92c 100644 --- a/rust/src/binary_view.rs +++ b/rust/src/binary_view.rs @@ -266,13 +266,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 { @@ -403,13 +398,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() { @@ -428,14 +421,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(), ); @@ -589,35 +580,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, ) @@ -716,11 +704,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) { @@ -767,11 +752,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; } @@ -779,11 +762,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() { @@ -877,27 +859,21 @@ pub trait BinaryViewExt: BinaryViewBase { 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, @@ -1109,24 +1085,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() { @@ -1136,13 +1107,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, ) }; @@ -1153,11 +1122,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); @@ -1171,10 +1136,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; } @@ -1185,10 +1149,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; } @@ -1199,7 +1162,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) } @@ -1236,14 +1199,9 @@ pub trait BinaryViewExt: BinaryViewBase { /// /// NOTE: This is different from setting a comment at the function-level. To set a comment in a /// function use [`Function::set_comment_at`] - fn set_comment_at(&self, addr: u64, comment: impl BnStrCompatible) { - let comment_raw = comment.into_bytes_with_nul(); + fn set_comment_at(&self, addr: u64, comment: impl AsCStr) { unsafe { - BNSetGlobalCommentForAddress( - self.as_ref().handle, - addr, - comment_raw.as_ref().as_ptr() as *const c_char, - ) + BNSetGlobalCommentForAddress(self.as_ref().handle, addr, comment.as_cstr().as_ptr()) } } @@ -1295,13 +1253,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 { @@ -1309,7 +1263,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>, { @@ -1317,7 +1271,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>, { @@ -1325,20 +1279,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. @@ -1462,14 +1411,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::ref_from_raw(h) }) } @@ -1478,14 +1421,8 @@ pub trait BinaryViewExt: BinaryViewBase { NonNull::new(result).map(|h| unsafe { Component::ref_from_raw(h) }) } - 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::ref_from_raw(h) }) } @@ -1494,8 +1431,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 { @@ -1516,39 +1452,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()), @@ -1580,7 +1505,7 @@ pub trait BinaryViewExt: BinaryViewBase { } // TODO: This is awful, rewrite this. - fn add_external_location( + fn add_external_location( &self, symbol: &Symbol, library: &ExternalLibrary, @@ -1588,7 +1513,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()); @@ -1597,7 +1521,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, ) @@ -1638,14 +1562,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) }) } @@ -1736,13 +1655,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) }) } @@ -1884,9 +1799,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(()); @@ -1926,8 +1841,7 @@ impl BinaryView { /// To avoid the above issue use [`crate::main_thread::execute_on_main_thread_and_wait`] to verify there /// are no queued up main thread actions. pub fn save_to_path(&self, file_path: impl AsRef) -> bool { - let file = file_path.as_ref().into_bytes_with_nul(); - unsafe { BNSaveToFilename(self.handle, file.as_ptr() as *mut _) } + unsafe { BNSaveToFilename(self.handle, file_path.as_ref().as_cstr().as_ptr()) } } /// Save the original binary file to the provided [`FileAccessor`] along with any modifications. diff --git a/rust/src/binary_view/memory_map.rs b/rust/src/binary_view/memory_map.rs index 3e248c545..9d8d6c761 100644 --- a/rust/src/binary_view/memory_map.rs +++ b/rust/src/binary_view/memory_map.rs @@ -3,9 +3,8 @@ use crate::data_buffer::DataBuffer; use crate::file_accessor::FileAccessor; use crate::rc::Ref; use crate::segment::SegmentFlags; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; use binaryninjacore_sys::*; -use std::ffi::c_char; #[derive(PartialEq, Eq, Hash)] pub struct MemoryMap { @@ -43,16 +42,15 @@ impl MemoryMap { pub fn add_binary_memory_region( &mut self, - name: impl BnStrCompatible, + name: impl AsCStr, start: u64, view: &BinaryView, segment_flags: Option, ) -> bool { - let name_raw = name.into_bytes_with_nul(); unsafe { BNAddBinaryMemoryRegion( self.view.handle, - name_raw.as_ref().as_ptr() as *const c_char, + name.as_cstr().as_ptr(), start, view.handle, segment_flags.unwrap_or_default().into_raw(), @@ -62,16 +60,15 @@ impl MemoryMap { pub fn add_data_memory_region( &mut self, - name: impl BnStrCompatible, + name: impl AsCStr, start: u64, data: &DataBuffer, segment_flags: Option, ) -> bool { - let name_raw = name.into_bytes_with_nul(); unsafe { BNAddDataMemoryRegion( self.view.handle, - name_raw.as_ref().as_ptr() as *const c_char, + name.as_cstr().as_ptr(), start, data.as_raw(), segment_flags.unwrap_or_default().into_raw(), @@ -81,16 +78,15 @@ impl MemoryMap { pub fn add_remote_memory_region( &mut self, - name: impl BnStrCompatible, + name: impl AsCStr, start: u64, accessor: &mut FileAccessor, segment_flags: Option, ) -> bool { - let name_raw = name.into_bytes_with_nul(); unsafe { BNAddRemoteMemoryRegion( self.view.handle, - name_raw.as_ref().as_ptr() as *const c_char, + name.as_cstr().as_ptr(), start, &mut accessor.api_object, segment_flags.unwrap_or_default().into_raw(), @@ -98,14 +94,8 @@ impl MemoryMap { } } - pub fn remove_memory_region(&mut self, name: impl BnStrCompatible) -> bool { - let name_raw = name.into_bytes_with_nul(); - unsafe { - BNRemoveMemoryRegion( - self.view.handle, - name_raw.as_ref().as_ptr() as *const c_char, - ) - } + pub fn remove_memory_region(&mut self, name: impl AsCStr) -> bool { + unsafe { BNRemoveMemoryRegion(self.view.handle, name.as_cstr().as_ptr()) } } pub fn active_memory_region_at(&self, addr: u64) -> BnString { @@ -115,98 +105,41 @@ impl MemoryMap { } } - pub fn memory_region_flags(&self, name: impl BnStrCompatible) -> SegmentFlags { - let name_raw = name.into_bytes_with_nul(); - let flags_raw = unsafe { - BNGetMemoryRegionFlags( - self.view.handle, - name_raw.as_ref().as_ptr() as *const c_char, - ) - }; + pub fn memory_region_flags(&self, name: impl AsCStr) -> SegmentFlags { + let flags_raw = + unsafe { BNGetMemoryRegionFlags(self.view.handle, name.as_cstr().as_ptr()) }; SegmentFlags::from_raw(flags_raw) } - pub fn set_memory_region_flags( - &mut self, - name: impl BnStrCompatible, - flags: SegmentFlags, - ) -> bool { - let name_raw = name.into_bytes_with_nul(); + pub fn set_memory_region_flags(&mut self, name: impl AsCStr, flags: SegmentFlags) -> bool { unsafe { - BNSetMemoryRegionFlags( - self.view.handle, - name_raw.as_ref().as_ptr() as *const c_char, - flags.into_raw(), - ) + BNSetMemoryRegionFlags(self.view.handle, name.as_cstr().as_ptr(), flags.into_raw()) } } - pub fn is_memory_region_enabled(&self, name: impl BnStrCompatible) -> bool { - let name_raw = name.into_bytes_with_nul(); - unsafe { - BNIsMemoryRegionEnabled( - self.view.handle, - name_raw.as_ref().as_ptr() as *const c_char, - ) - } + pub fn is_memory_region_enabled(&self, name: impl AsCStr) -> bool { + unsafe { BNIsMemoryRegionEnabled(self.view.handle, name.as_cstr().as_ptr()) } } - pub fn set_memory_region_enabled(&mut self, name: impl BnStrCompatible, enabled: bool) -> bool { - let name_raw = name.into_bytes_with_nul(); - unsafe { - BNSetMemoryRegionEnabled( - self.view.handle, - name_raw.as_ref().as_ptr() as *const c_char, - enabled, - ) - } + pub fn set_memory_region_enabled(&mut self, name: impl AsCStr, enabled: bool) -> bool { + unsafe { BNSetMemoryRegionEnabled(self.view.handle, name.as_cstr().as_ptr(), enabled) } } // TODO: Should we just call this is_memory_region_relocatable? - pub fn is_memory_region_rebaseable(&self, name: impl BnStrCompatible) -> bool { - let name_raw = name.into_bytes_with_nul(); - unsafe { - BNIsMemoryRegionRebaseable( - self.view.handle, - name_raw.as_ref().as_ptr() as *const c_char, - ) - } + pub fn is_memory_region_rebaseable(&self, name: impl AsCStr) -> bool { + unsafe { BNIsMemoryRegionRebaseable(self.view.handle, name.as_cstr().as_ptr()) } } - pub fn set_memory_region_rebaseable( - &mut self, - name: impl BnStrCompatible, - enabled: bool, - ) -> bool { - let name_raw = name.into_bytes_with_nul(); - unsafe { - BNSetMemoryRegionRebaseable( - self.view.handle, - name_raw.as_ref().as_ptr() as *const c_char, - enabled, - ) - } + pub fn set_memory_region_rebaseable(&mut self, name: impl AsCStr, enabled: bool) -> bool { + unsafe { BNSetMemoryRegionRebaseable(self.view.handle, name.as_cstr().as_ptr(), enabled) } } - pub fn memory_region_fill(&self, name: impl BnStrCompatible) -> u8 { - let name_raw = name.into_bytes_with_nul(); - unsafe { - BNGetMemoryRegionFill( - self.view.handle, - name_raw.as_ref().as_ptr() as *const c_char, - ) - } + pub fn memory_region_fill(&self, name: impl AsCStr) -> u8 { + unsafe { BNGetMemoryRegionFill(self.view.handle, name.as_cstr().as_ptr()) } } - pub fn set_memory_region_fill(&mut self, name: impl BnStrCompatible, fill: u8) -> bool { - let name_raw = name.into_bytes_with_nul(); - unsafe { - BNSetMemoryRegionFill( - self.view.handle, - name_raw.as_ref().as_ptr() as *const c_char, - fill, - ) - } + pub fn set_memory_region_fill(&mut self, name: impl AsCStr, fill: u8) -> bool { + unsafe { BNSetMemoryRegionFill(self.view.handle, name.as_cstr().as_ptr(), fill) } } pub fn reset(&mut self) { diff --git a/rust/src/calling_convention.rs b/rust/src/calling_convention.rs index 9c1493e1f..8043ea566 100644 --- a/rust/src/calling_convention.rs +++ b/rust/src/calling_convention.rs @@ -58,7 +58,7 @@ pub trait CallingConvention: Sync { pub fn register_calling_convention(arch: &A, name: N, cc: C) -> Ref where A: Architecture, - N: BnStrCompatible, + N: AsCStr, C: 'static + CallingConvention, { struct CustomCallingConventionContext @@ -377,7 +377,6 @@ where ) } - let name = name.into_bytes_with_nul(); let raw = Box::into_raw(Box::new(CustomCallingConventionContext { raw_handle: std::ptr::null_mut(), cc, @@ -413,8 +412,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/collaboration.rs b/rust/src/collaboration.rs index c90677622..2f185fbfc 100644 --- a/rust/src/collaboration.rs +++ b/rust/src/collaboration.rs @@ -22,7 +22,6 @@ pub use permission::*; pub use project::*; pub use remote::*; pub use snapshot::*; -use std::ffi::c_char; use std::ptr::NonNull; pub use sync::*; pub use user::*; @@ -30,7 +29,7 @@ pub use user::*; use binaryninjacore_sys::*; use crate::rc::{Array, Ref}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; // TODO: Should we pull metadata and information required to call a function? Or should we add documentation // TODO: on what functions need to have been called prior? I feel like we should make the user have to pull @@ -73,24 +72,20 @@ pub fn known_remotes() -> Array { } /// Get Remote by unique `id` -pub fn get_remote_by_id(id: S) -> Option> { - let id = id.into_bytes_with_nul(); - let value = unsafe { BNCollaborationGetRemoteById(id.as_ref().as_ptr() as *const c_char) }; +pub fn get_remote_by_id(id: S) -> Option> { + let value = unsafe { BNCollaborationGetRemoteById(id.as_cstr().as_ptr()) }; NonNull::new(value).map(|h| unsafe { Remote::ref_from_raw(h) }) } /// Get Remote by `address` -pub fn get_remote_by_address(address: S) -> Option> { - let address = address.into_bytes_with_nul(); - let value = - unsafe { BNCollaborationGetRemoteByAddress(address.as_ref().as_ptr() as *const c_char) }; +pub fn get_remote_by_address(address: S) -> Option> { + let value = unsafe { BNCollaborationGetRemoteByAddress(address.as_cstr().as_ptr()) }; NonNull::new(value).map(|h| unsafe { Remote::ref_from_raw(h) }) } /// Get Remote by `name` -pub fn get_remote_by_name(name: S) -> Option> { - let name = name.into_bytes_with_nul(); - let value = unsafe { BNCollaborationGetRemoteByName(name.as_ref().as_ptr() as *const c_char) }; +pub fn get_remote_by_name(name: S) -> Option> { + let value = unsafe { BNCollaborationGetRemoteByName(name.as_cstr().as_ptr()) }; NonNull::new(value).map(|h| unsafe { Remote::ref_from_raw(h) }) } @@ -106,58 +101,44 @@ pub fn save_remotes() { pub fn store_data_in_keychain(key: K, data: I) -> bool where - K: BnStrCompatible, + K: AsCStr, I: IntoIterator, - DK: BnStrCompatible, - DV: BnStrCompatible, + DK: AsCStr, + DV: AsCStr, { - let key = key.into_bytes_with_nul(); - let (data_keys, data_values): (Vec, Vec) = data - .into_iter() - .map(|(k, v)| (k.into_bytes_with_nul(), v.into_bytes_with_nul())) - .unzip(); - let data_keys_ptr: Box<[*const c_char]> = data_keys - .iter() - .map(|k| k.as_ref().as_ptr() as *const c_char) - .collect(); - let data_values_ptr: Box<[*const c_char]> = data_values - .iter() - .map(|v| v.as_ref().as_ptr() as *const c_char) - .collect(); + let (keys, values): (Vec<_>, Vec<_>) = data.into_iter().unzip(); + + let data_keys = keys.iter().map(|k| k.as_cstr()).collect::>(); + let mut data_keys_ptrs = data_keys.iter().map(|k| k.as_ptr()).collect::>(); + + let data_values = values.iter().map(|v| v.as_cstr()).collect::>(); + let mut data_values_ptrs = data_values.iter().map(|v| v.as_ptr()).collect::>(); + unsafe { BNCollaborationStoreDataInKeychain( - key.as_ref().as_ptr() as *const c_char, - data_keys_ptr.as_ptr() as *mut _, - data_values_ptr.as_ptr() as *mut _, + key.as_cstr().as_ptr(), + data_keys_ptrs.as_mut_ptr(), + data_values_ptrs.as_mut_ptr(), data_keys.len(), ) } } -pub fn has_data_in_keychain(key: K) -> bool { - let key = key.into_bytes_with_nul(); - unsafe { BNCollaborationHasDataInKeychain(key.as_ref().as_ptr() as *const c_char) } +pub fn has_data_in_keychain(key: K) -> bool { + unsafe { BNCollaborationHasDataInKeychain(key.as_cstr().as_ptr()) } } -pub fn get_data_from_keychain( - key: K, -) -> Option<(Array, Array)> { - let key = key.into_bytes_with_nul(); +pub fn get_data_from_keychain(key: K) -> Option<(Array, Array)> { let mut keys = std::ptr::null_mut(); let mut values = std::ptr::null_mut(); let count = unsafe { - BNCollaborationGetDataFromKeychain( - key.as_ref().as_ptr() as *const c_char, - &mut keys, - &mut values, - ) + BNCollaborationGetDataFromKeychain(key.as_cstr().as_ptr(), &mut keys, &mut values) }; let keys = (!keys.is_null()).then(|| unsafe { Array::new(keys, count, ()) }); let values = (!values.is_null()).then(|| unsafe { Array::new(values, count, ()) }); keys.zip(values) } -pub fn delete_data_from_keychain(key: K) -> bool { - let key = key.into_bytes_with_nul(); - unsafe { BNCollaborationDeleteDataFromKeychain(key.as_ref().as_ptr() as *const c_char) } +pub fn delete_data_from_keychain(key: K) -> bool { + unsafe { BNCollaborationDeleteDataFromKeychain(key.as_cstr().as_ptr()) } } diff --git a/rust/src/collaboration/changeset.rs b/rust/src/collaboration/changeset.rs index 9d7cdb7c3..7e522a0ea 100644 --- a/rust/src/collaboration/changeset.rs +++ b/rust/src/collaboration/changeset.rs @@ -1,5 +1,4 @@ use binaryninjacore_sys::*; -use std::ffi::c_char; use std::ptr::NonNull; use super::{RemoteFile, RemoteUser}; @@ -7,7 +6,7 @@ use super::{RemoteFile, RemoteUser}; use crate::database::snapshot::SnapshotId; use crate::database::Database; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; /// A collection of snapshots in a local database #[repr(transparent)] @@ -66,14 +65,8 @@ impl Changeset { } /// Set the name of the changeset, e.g. in a name changeset function. - pub fn set_name(&self, value: S) -> bool { - let value = value.into_bytes_with_nul(); - unsafe { - BNCollaborationChangesetSetName( - self.handle.as_ptr(), - value.as_ref().as_ptr() as *const c_char, - ) - } + pub fn set_name(&self, value: S) -> bool { + unsafe { BNCollaborationChangesetSetName(self.handle.as_ptr(), value.as_cstr().as_ptr()) } } } diff --git a/rust/src/collaboration/file.rs b/rust/src/collaboration/file.rs index 2651d3c77..a58152248 100644 --- a/rust/src/collaboration/file.rs +++ b/rust/src/collaboration/file.rs @@ -1,4 +1,4 @@ -use std::ffi::{c_char, c_void}; +use std::ffi::c_void; use std::fmt::{Debug, Formatter}; use std::ptr::NonNull; use std::time::SystemTime; @@ -16,7 +16,7 @@ use crate::file_metadata::FileMetadata; use crate::progress::{NoProgressCallback, ProgressCallback, SplitProgressBuilder}; use crate::project::file::ProjectFile; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; pub type RemoteFileType = BNRemoteFileType; @@ -94,14 +94,9 @@ impl RemoteFile { success.then_some(()).ok_or(()) } - pub fn set_metadata(&self, folder: S) -> Result<(), ()> { - let folder_raw = folder.into_bytes_with_nul(); - let success = unsafe { - BNRemoteFileSetMetadata( - self.handle.as_ptr(), - folder_raw.as_ref().as_ptr() as *const c_char, - ) - }; + pub fn set_metadata(&self, folder: S) -> Result<(), ()> { + let success = + unsafe { BNRemoteFileSetMetadata(self.handle.as_ptr(), folder.as_cstr().as_ptr()) }; success.then_some(()).ok_or(()) } @@ -190,14 +185,8 @@ impl RemoteFile { } /// Set the description of the file. You will need to push the file to update the remote version. - pub fn set_name(&self, name: S) -> Result<(), ()> { - let name = name.into_bytes_with_nul(); - let success = unsafe { - BNRemoteFileSetName( - self.handle.as_ptr(), - name.as_ref().as_ptr() as *const c_char, - ) - }; + pub fn set_name(&self, name: S) -> Result<(), ()> { + let success = unsafe { BNRemoteFileSetName(self.handle.as_ptr(), name.as_cstr().as_ptr()) }; success.then_some(()).ok_or(()) } @@ -209,13 +198,9 @@ impl RemoteFile { } /// Set the description of the file. You will need to push the file to update the remote version. - pub fn set_description(&self, description: S) -> Result<(), ()> { - let description = description.into_bytes_with_nul(); + pub fn set_description(&self, description: S) -> Result<(), ()> { let success = unsafe { - BNRemoteFileSetDescription( - self.handle.as_ptr(), - description.as_ref().as_ptr() as *const c_char, - ) + BNRemoteFileSetDescription(self.handle.as_ptr(), description.as_cstr().as_ptr()) }; success.then_some(()).ok_or(()) } @@ -263,18 +248,13 @@ impl RemoteFile { /// Get a specific Snapshot in the File by its id /// /// NOTE: If snapshots have not been pulled, they will be pulled upon calling this. - pub fn snapshot_by_id( - &self, - id: S, - ) -> Result>, ()> { + pub fn snapshot_by_id(&self, id: S) -> Result>, ()> { // TODO: This sync should be removed? if !self.has_pulled_snapshots() { self.pull_snapshots()?; } - let id = id.into_bytes_with_nul(); - let result = unsafe { - BNRemoteFileGetSnapshotById(self.handle.as_ptr(), id.as_ref().as_ptr() as *const c_char) - }; + let result = + unsafe { BNRemoteFileGetSnapshotById(self.handle.as_ptr(), id.as_cstr().as_ptr()) }; Ok(NonNull::new(result).map(|handle| unsafe { RemoteSnapshot::ref_from_raw(handle) })) } @@ -314,9 +294,9 @@ impl RemoteFile { parent_ids: I, ) -> Result, ()> where - S: BnStrCompatible, + S: AsCStr, I: IntoIterator, - I::Item: BnStrCompatible, + I::Item: AsCStr, { self.create_snapshot_with_progress( name, @@ -346,24 +326,18 @@ impl RemoteFile { mut progress: P, ) -> Result, ()> where - S: BnStrCompatible, + S: AsCStr, P: ProgressCallback, I: IntoIterator, - I::Item: BnStrCompatible, + I::Item: AsCStr, { - let name = name.into_bytes_with_nul(); - let parent_ids: Vec<_> = parent_ids - .into_iter() - .map(|id| id.into_bytes_with_nul()) - .collect(); - let mut parent_ids_raw: Vec<_> = parent_ids - .iter() - .map(|x| x.as_ref().as_ptr() as *const c_char) - .collect(); + let parent_ids = parent_ids.into_iter().collect::>(); + let parent_ids = parent_ids.iter().map(|id| id.as_cstr()).collect::>(); + let mut parent_ids_raw = parent_ids.iter().map(|x| x.as_ptr()).collect::>(); let result = unsafe { BNRemoteFileCreateSnapshot( self.handle.as_ptr(), - name.as_ref().as_ptr() as *const c_char, + name.as_cstr().as_ptr(), contents.as_mut_ptr(), contents.len(), analysis_cache_contexts.as_mut_ptr(), @@ -428,10 +402,7 @@ impl RemoteFile { /// /// * `db_path` - File path for saved database /// * `progress_function` - Function to call for progress updates - pub fn download(&self, db_path: S) -> Result, ()> - where - S: BnStrCompatible, - { + pub fn download(&self, db_path: S) -> Result, ()> { sync::download_file(self, db_path) } @@ -447,14 +418,14 @@ impl RemoteFile { progress_function: F, ) -> Result, ()> where - S: BnStrCompatible, + S: AsCStr, F: ProgressCallback, { sync::download_file_with_progress(self, db_path, progress_function) } /// Download a remote file and save it to a BNDB at the given `path`, returning the associated [`FileMetadata`]. - pub fn download_database(&self, path: S) -> Result, ()> { + pub fn download_database(&self, path: S) -> Result, ()> { let file = self.download(path)?; let database = file.database().ok_or(())?; self.sync(&database, DatabaseConflictHandlerFail, NoNameChangeset)?; @@ -464,7 +435,7 @@ impl RemoteFile { // TODO: This might be a bad helper... maybe remove... // TODO: AsRef /// Download a remote file and save it to a BNDB at the given `path`. - pub fn download_database_with_progress( + pub fn download_database_with_progress( &self, path: S, progress: impl ProgressCallback, diff --git a/rust/src/collaboration/folder.rs b/rust/src/collaboration/folder.rs index 90a85f1cf..2f3731904 100644 --- a/rust/src/collaboration/folder.rs +++ b/rust/src/collaboration/folder.rs @@ -1,11 +1,10 @@ use super::{Remote, RemoteProject}; use binaryninjacore_sys::*; -use std::ffi::c_char; use std::ptr::NonNull; use crate::project::folder::ProjectFolder; use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; #[repr(transparent)] pub struct RemoteFolder { @@ -104,14 +103,9 @@ impl RemoteFolder { } /// Set the display name of the folder. You will need to push the folder to update the remote version. - pub fn set_name(&self, name: S) -> Result<(), ()> { - let name = name.into_bytes_with_nul(); - let success = unsafe { - BNRemoteFolderSetName( - self.handle.as_ptr(), - name.as_ref().as_ptr() as *const c_char, - ) - }; + pub fn set_name(&self, name: S) -> Result<(), ()> { + let success = + unsafe { BNRemoteFolderSetName(self.handle.as_ptr(), name.as_cstr().as_ptr()) }; success.then_some(()).ok_or(()) } @@ -123,13 +117,9 @@ impl RemoteFolder { } /// Set the description of the folder. You will need to push the folder to update the remote version. - pub fn set_description(&self, description: S) -> Result<(), ()> { - let description = description.into_bytes_with_nul(); + pub fn set_description(&self, description: S) -> Result<(), ()> { let success = unsafe { - BNRemoteFolderSetDescription( - self.handle.as_ptr(), - description.as_ref().as_ptr() as *const c_char, - ) + BNRemoteFolderSetDescription(self.handle.as_ptr(), description.as_cstr().as_ptr()) }; success.then_some(()).ok_or(()) } diff --git a/rust/src/collaboration/group.rs b/rust/src/collaboration/group.rs index bad09d6cb..b79daf9bd 100644 --- a/rust/src/collaboration/group.rs +++ b/rust/src/collaboration/group.rs @@ -1,8 +1,7 @@ use super::Remote; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; use binaryninjacore_sys::*; -use std::ffi::c_char; use std::fmt; use std::fmt::{Display, Formatter}; use std::ptr::NonNull; @@ -50,14 +49,8 @@ impl RemoteGroup { /// Set group name /// You will need to push the group to update the Remote. - pub fn set_name(&self, name: U) { - let name = name.into_bytes_with_nul(); - unsafe { - BNCollaborationGroupSetName( - self.handle.as_ptr(), - name.as_ref().as_ptr() as *const c_char, - ) - } + pub fn set_name(&self, name: U) { + unsafe { BNCollaborationGroupSetName(self.handle.as_ptr(), name.as_cstr().as_ptr()) } } /// Get list of users in the group @@ -90,16 +83,11 @@ impl RemoteGroup { pub fn set_users(&self, usernames: I) -> Result<(), ()> where I: IntoIterator, - I::Item: BnStrCompatible, + I::Item: AsCStr, { - let usernames: Vec<_> = usernames - .into_iter() - .map(|u| u.into_bytes_with_nul()) - .collect(); - let mut usernames_raw: Vec<_> = usernames - .iter() - .map(|s| s.as_ref().as_ptr() as *const c_char) - .collect(); + let usernames = usernames.into_iter().collect::>(); + let usernames = usernames.iter().map(|u| u.as_cstr()).collect::>(); + let mut usernames_raw = usernames.iter().map(|s| s.as_ptr()).collect::>(); // TODO: This should only fail if collaboration is not supported. // TODO: Because you should not have a RemoteGroup at that point we can ignore? // TODO: Do you need any permissions to do this? @@ -114,13 +102,9 @@ impl RemoteGroup { } /// Test if a group has a user with the given username - pub fn contains_user(&self, username: U) -> bool { - let username = username.into_bytes_with_nul(); + pub fn contains_user(&self, username: U) -> bool { unsafe { - BNCollaborationGroupContainsUser( - self.handle.as_ptr(), - username.as_ref().as_ptr() as *const c_char, - ) + BNCollaborationGroupContainsUser(self.handle.as_ptr(), username.as_cstr().as_ptr()) } } } diff --git a/rust/src/collaboration/merge.rs b/rust/src/collaboration/merge.rs index 2d28725c2..00cfb90d1 100644 --- a/rust/src/collaboration/merge.rs +++ b/rust/src/collaboration/merge.rs @@ -1,11 +1,10 @@ use binaryninjacore_sys::*; -use std::ffi::c_char; use std::ptr::NonNull; use crate::database::{snapshot::Snapshot, Database}; use crate::file_metadata::FileMetadata; use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; pub type MergeConflictDataType = BNMergeConflictDataType; @@ -49,13 +48,9 @@ impl MergeConflict { NonNull::new(result).map(|handle| unsafe { Snapshot::from_raw(handle) }) } - pub fn path_item_string(&self, path: S) -> Result { - let path = path.into_bytes_with_nul(); + pub fn path_item_string(&self, path: S) -> Result { let result = unsafe { - BNAnalysisMergeConflictGetPathItemString( - self.handle.as_ptr(), - path.as_ref().as_ptr() as *const c_char, - ) + BNAnalysisMergeConflictGetPathItemString(self.handle.as_ptr(), path.as_cstr().as_ptr()) }; (!result.is_null()) .then(|| unsafe { BnString::from_raw(result) }) @@ -123,25 +118,17 @@ impl MergeConflict { } /// Call this when you've resolved the conflict to save the result - pub fn success(&self, value: S) -> Result<(), ()> { - let value = value.into_bytes_with_nul(); + pub fn success(&self, value: S) -> Result<(), ()> { let success = unsafe { - BNAnalysisMergeConflictSuccess( - self.handle.as_ptr(), - value.as_ref().as_ptr() as *const c_char, - ) + BNAnalysisMergeConflictSuccess(self.handle.as_ptr(), value.as_cstr().as_ptr()) }; success.then_some(()).ok_or(()) } // TODO: Make a safe version of this that checks the path and if it holds a number - pub unsafe fn get_path_item_number(&self, path_key: S) -> Option { - let path_key = path_key.into_bytes_with_nul(); + pub unsafe fn get_path_item_number(&self, path_key: S) -> Option { let value = unsafe { - BNAnalysisMergeConflictGetPathItem( - self.handle.as_ptr(), - path_key.as_ref().as_ptr() as *const c_char, - ) + BNAnalysisMergeConflictGetPathItem(self.handle.as_ptr(), path_key.as_cstr().as_ptr()) }; match value.is_null() { // SAFETY: The path must be a number. @@ -150,12 +137,11 @@ impl MergeConflict { } } - pub unsafe fn get_path_item_string(&self, path_key: S) -> Option { - let path_key = path_key.into_bytes_with_nul(); + pub unsafe fn get_path_item_string(&self, path_key: S) -> Option { let value = unsafe { BNAnalysisMergeConflictGetPathItemString( self.handle.as_ptr(), - path_key.as_ref().as_ptr() as *const c_char, + path_key.as_cstr().as_ptr(), ) }; match value.is_null() { diff --git a/rust/src/collaboration/project.rs b/rust/src/collaboration/project.rs index 1455f6c31..3f5f9a2fd 100644 --- a/rust/src/collaboration/project.rs +++ b/rust/src/collaboration/project.rs @@ -1,4 +1,4 @@ -use std::ffi::{c_char, c_void}; +use std::ffi::c_void; use std::ptr::NonNull; use std::time::SystemTime; @@ -15,7 +15,7 @@ use crate::file_metadata::FileMetadata; use crate::progress::{NoProgressCallback, ProgressCallback}; use crate::project::Project; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; #[repr(transparent)] pub struct RemoteProject { @@ -136,14 +136,9 @@ impl RemoteProject { } /// Set the description of the file. You will need to push the file to update the remote version. - pub fn set_name(&self, name: S) -> Result<(), ()> { - let name = name.into_bytes_with_nul(); - let success = unsafe { - BNRemoteProjectSetName( - self.handle.as_ptr(), - name.as_ref().as_ptr() as *const c_char, - ) - }; + pub fn set_name(&self, name: S) -> Result<(), ()> { + let success = + unsafe { BNRemoteProjectSetName(self.handle.as_ptr(), name.as_cstr().as_ptr()) }; success.then_some(()).ok_or(()) } @@ -155,13 +150,9 @@ impl RemoteProject { } /// Set the description of the file. You will need to push the file to update the remote version. - pub fn set_description(&self, description: S) -> Result<(), ()> { - let description = description.into_bytes_with_nul(); + pub fn set_description(&self, description: S) -> Result<(), ()> { let success = unsafe { - BNRemoteProjectSetDescription( - self.handle.as_ptr(), - description.as_ref().as_ptr() as *const c_char, - ) + BNRemoteProjectSetDescription(self.handle.as_ptr(), description.as_cstr().as_ptr()) }; success.then_some(()).ok_or(()) } @@ -230,15 +221,13 @@ impl RemoteProject { /// /// NOTE: If the project has not been opened, it will be opened upon calling this. /// NOTE: If files have not been pulled, they will be pulled upon calling this. - pub fn get_file_by_id(&self, id: S) -> Result>, ()> { + pub fn get_file_by_id(&self, id: S) -> Result>, ()> { // TODO: This sync should be removed? if !self.has_pulled_files() { self.pull_files()?; } - let id = id.into_bytes_with_nul(); - let result = unsafe { - BNRemoteProjectGetFileById(self.handle.as_ptr(), id.as_ref().as_ptr() as *const c_char) - }; + let result = + unsafe { BNRemoteProjectGetFileById(self.handle.as_ptr(), id.as_cstr().as_ptr()) }; Ok(NonNull::new(result).map(|handle| unsafe { RemoteFile::ref_from_raw(handle) })) } @@ -246,21 +235,13 @@ impl RemoteProject { /// /// NOTE: If the project has not been opened, it will be opened upon calling this. /// NOTE: If files have not been pulled, they will be pulled upon calling this. - pub fn get_file_by_name( - &self, - name: S, - ) -> Result>, ()> { + pub fn get_file_by_name(&self, name: S) -> Result>, ()> { // TODO: This sync should be removed? if !self.has_pulled_files() { self.pull_files()?; } - let id = name.into_bytes_with_nul(); - let result = unsafe { - BNRemoteProjectGetFileByName( - self.handle.as_ptr(), - id.as_ref().as_ptr() as *const c_char, - ) - }; + let result = + unsafe { BNRemoteProjectGetFileByName(self.handle.as_ptr(), name.as_cstr().as_ptr()) }; Ok(NonNull::new(result).map(|handle| unsafe { RemoteFile::ref_from_raw(handle) })) } @@ -311,9 +292,9 @@ impl RemoteProject { file_type: RemoteFileType, ) -> Result, ()> where - F: BnStrCompatible, - N: BnStrCompatible, - D: BnStrCompatible, + F: AsCStr, + N: AsCStr, + D: AsCStr, { self.create_file_with_progress( filename, @@ -348,26 +329,23 @@ impl RemoteProject { mut progress: P, ) -> Result, ()> where - F: BnStrCompatible, - N: BnStrCompatible, - D: BnStrCompatible, + F: AsCStr, + N: AsCStr, + D: AsCStr, P: ProgressCallback, { // TODO: This sync should be removed? self.open()?; - let filename = filename.into_bytes_with_nul(); - let name = name.into_bytes_with_nul(); - let description = description.into_bytes_with_nul(); let folder_handle = parent_folder.map_or(std::ptr::null_mut(), |f| f.handle.as_ptr()); let file_ptr = unsafe { BNRemoteProjectCreateFile( self.handle.as_ptr(), - filename.as_ref().as_ptr() as *const c_char, + filename.as_cstr().as_ptr(), contents.as_ptr() as *mut _, contents.len(), - name.as_ref().as_ptr() as *const c_char, - description.as_ref().as_ptr() as *const c_char, + name.as_cstr().as_ptr(), + description.as_cstr().as_ptr(), folder_handle, file_type, Some(P::cb_progress_callback), @@ -386,24 +364,20 @@ impl RemoteProject { pub fn push_file(&self, file: &RemoteFile, extra_fields: I) -> Result<(), ()> where I: Iterator, - K: BnStrCompatible, - V: BnStrCompatible, + K: AsCStr, + V: AsCStr, { // TODO: This sync should be removed? self.open()?; - let (keys, values): (Vec<_>, Vec<_>) = extra_fields - .into_iter() - .map(|(k, v)| (k.into_bytes_with_nul(), v.into_bytes_with_nul())) - .unzip(); - let mut keys_raw = keys - .iter() - .map(|s| s.as_ref().as_ptr() as *const c_char) - .collect::>(); - let mut values_raw = values - .iter() - .map(|s| s.as_ref().as_ptr() as *const c_char) - .collect::>(); + let (keys, values): (Vec<_>, Vec<_>) = extra_fields.into_iter().unzip(); + + let keys = keys.iter().map(|k| k.as_cstr()).collect::>(); + let mut keys_raw = keys.iter().map(|s| s.as_ptr()).collect::>(); + + let values = values.iter().map(|v| v.as_cstr()).collect::>(); + let mut values_raw = values.iter().map(|v| v.as_ptr()).collect::>(); + let success = unsafe { BNRemoteProjectPushFile( self.handle.as_ptr(), @@ -446,21 +420,13 @@ impl RemoteProject { /// /// NOTE: If the project has not been opened, it will be opened upon calling this. /// NOTE: If folders have not been pulled, they will be pulled upon calling this. - pub fn get_folder_by_id( - &self, - id: S, - ) -> Result>, ()> { + pub fn get_folder_by_id(&self, id: S) -> Result>, ()> { // TODO: This sync should be removed? if !self.has_pulled_folders() { self.pull_folders()?; } - let id = id.into_bytes_with_nul(); - let result = unsafe { - BNRemoteProjectGetFolderById( - self.handle.as_ptr(), - id.as_ref().as_ptr() as *const c_char, - ) - }; + let result = + unsafe { BNRemoteProjectGetFolderById(self.handle.as_ptr(), id.as_cstr().as_ptr()) }; Ok(NonNull::new(result).map(|handle| unsafe { RemoteFolder::ref_from_raw(handle) })) } @@ -505,8 +471,8 @@ impl RemoteProject { parent_folder: Option<&RemoteFolder>, ) -> Result, ()> where - N: BnStrCompatible, - D: BnStrCompatible, + N: AsCStr, + D: AsCStr, { self.create_folder_with_progress(name, description, parent_folder, NoProgressCallback) } @@ -527,21 +493,19 @@ impl RemoteProject { mut progress: P, ) -> Result, ()> where - N: BnStrCompatible, - D: BnStrCompatible, + N: AsCStr, + D: AsCStr, P: ProgressCallback, { // TODO: This sync should be removed? self.open()?; - let name = name.into_bytes_with_nul(); - let description = description.into_bytes_with_nul(); let folder_handle = parent_folder.map_or(std::ptr::null_mut(), |f| f.handle.as_ptr()); let file_ptr = unsafe { BNRemoteProjectCreateFolder( self.handle.as_ptr(), - name.as_ref().as_ptr() as *const c_char, - description.as_ref().as_ptr() as *const c_char, + name.as_cstr().as_ptr(), + description.as_cstr().as_ptr(), folder_handle, Some(P::cb_progress_callback), &mut progress as *mut P as *mut c_void, @@ -562,24 +526,20 @@ impl RemoteProject { pub fn push_folder(&self, folder: &RemoteFolder, extra_fields: I) -> Result<(), ()> where I: Iterator, - K: BnStrCompatible, - V: BnStrCompatible, + K: AsCStr, + V: AsCStr, { // TODO: This sync should be removed? self.open()?; - let (keys, values): (Vec<_>, Vec<_>) = extra_fields - .into_iter() - .map(|(k, v)| (k.into_bytes_with_nul(), v.into_bytes_with_nul())) - .unzip(); - let mut keys_raw = keys - .iter() - .map(|s| s.as_ref().as_ptr() as *const c_char) - .collect::>(); - let mut values_raw = values - .iter() - .map(|s| s.as_ref().as_ptr() as *const c_char) - .collect::>(); + let (keys, values): (Vec<_>, Vec<_>) = extra_fields.into_iter().unzip(); + + let keys = keys.iter().map(|k| k.as_cstr()).collect::>(); + let mut keys_raw = keys.iter().map(|s| s.as_ptr()).collect::>(); + + let values = values.iter().map(|v| v.as_cstr()).collect::>(); + let mut values_raw = values.iter().map(|v| v.as_ptr()).collect::>(); + let success = unsafe { BNRemoteProjectPushFolder( self.handle.as_ptr(), @@ -637,10 +597,7 @@ impl RemoteProject { /// Get a specific permission in the Project by its id. /// /// NOTE: If group or user permissions have not been pulled, they will be pulled upon calling this. - pub fn get_permission_by_id( - &self, - id: S, - ) -> Result>, ()> { + pub fn get_permission_by_id(&self, id: S) -> Result>, ()> { // TODO: This sync should be removed? if !self.has_pulled_user_permissions() { self.pull_user_permissions()?; @@ -650,9 +607,8 @@ impl RemoteProject { self.pull_group_permissions()?; } - let id = id.into_bytes_with_nul(); let value = unsafe { - BNRemoteProjectGetPermissionById(self.handle.as_ptr(), id.as_ref().as_ptr() as *const _) + BNRemoteProjectGetPermissionById(self.handle.as_ptr(), id.as_cstr().as_ptr()) }; Ok(NonNull::new(value).map(|v| unsafe { Permission::ref_from_raw(v) })) } @@ -745,7 +701,7 @@ impl RemoteProject { /// /// * `user_id` - User id /// * `level` - Permission level - pub fn create_user_permission( + pub fn create_user_permission( &self, user_id: S, level: CollaborationPermissionLevel, @@ -760,17 +716,16 @@ impl RemoteProject { /// * `user_id` - User id /// * `level` - Permission level /// * `progress` - The progress callback to call - pub fn create_user_permission_with_progress( + pub fn create_user_permission_with_progress( &self, user_id: S, level: CollaborationPermissionLevel, mut progress: F, ) -> Result, ()> { - let user_id = user_id.into_bytes_with_nul(); let value = unsafe { BNRemoteProjectCreateUserPermission( self.handle.as_ptr(), - user_id.as_ref().as_ptr() as *const c_char, + user_id.as_cstr().as_ptr(), level, Some(F::cb_progress_callback), &mut progress as *mut F as *mut c_void, @@ -795,21 +750,16 @@ impl RemoteProject { ) -> Result<(), ()> where I: Iterator, - K: BnStrCompatible, - V: BnStrCompatible, + K: AsCStr, + V: AsCStr, { - let (keys, values): (Vec<_>, Vec<_>) = extra_fields - .into_iter() - .map(|(k, v)| (k.into_bytes_with_nul(), v.into_bytes_with_nul())) - .unzip(); - let mut keys_raw = keys - .iter() - .map(|s| s.as_ref().as_ptr() as *const c_char) - .collect::>(); - let mut values_raw = values - .iter() - .map(|s| s.as_ref().as_ptr() as *const c_char) - .collect::>(); + let (keys, values): (Vec<_>, Vec<_>) = extra_fields.into_iter().unzip(); + + let keys = keys.iter().map(|k| k.as_cstr()).collect::>(); + let mut keys_raw = keys.iter().map(|s| s.as_ptr()).collect::>(); + + let values = values.iter().map(|v| v.as_cstr()).collect::>(); + let mut values_raw = values.iter().map(|v| v.as_ptr()).collect::>(); let success = unsafe { BNRemoteProjectPushPermission( @@ -836,14 +786,8 @@ impl RemoteProject { /// # Arguments /// /// * `username` - Username of user to check - pub fn can_user_view(&self, username: S) -> bool { - let username = username.into_bytes_with_nul(); - unsafe { - BNRemoteProjectCanUserView( - self.handle.as_ptr(), - username.as_ref().as_ptr() as *const c_char, - ) - } + pub fn can_user_view(&self, username: S) -> bool { + unsafe { BNRemoteProjectCanUserView(self.handle.as_ptr(), username.as_cstr().as_ptr()) } } /// Determine if a user is in any of the edit/admin groups. @@ -851,14 +795,8 @@ impl RemoteProject { /// # Arguments /// /// * `username` - Username of user to check - pub fn can_user_edit(&self, username: S) -> bool { - let username = username.into_bytes_with_nul(); - unsafe { - BNRemoteProjectCanUserEdit( - self.handle.as_ptr(), - username.as_ref().as_ptr() as *const c_char, - ) - } + pub fn can_user_edit(&self, username: S) -> bool { + unsafe { BNRemoteProjectCanUserEdit(self.handle.as_ptr(), username.as_cstr().as_ptr()) } } /// Determine if a user is in the admin group. @@ -866,14 +804,8 @@ impl RemoteProject { /// # Arguments /// /// * `username` - Username of user to check - pub fn can_user_admin(&self, username: S) -> bool { - let username = username.into_bytes_with_nul(); - unsafe { - BNRemoteProjectCanUserAdmin( - self.handle.as_ptr(), - username.as_ref().as_ptr() as *const c_char, - ) - } + pub fn can_user_admin(&self, username: S) -> bool { + unsafe { BNRemoteProjectCanUserAdmin(self.handle.as_ptr(), username.as_cstr().as_ptr()) } } /// Get the default directory path for a remote Project. This is based off diff --git a/rust/src/collaboration/remote.rs b/rust/src/collaboration/remote.rs index c12504033..7932b07fc 100644 --- a/rust/src/collaboration/remote.rs +++ b/rust/src/collaboration/remote.rs @@ -1,5 +1,5 @@ use binaryninjacore_sys::*; -use std::ffi::{c_char, c_void}; +use std::ffi::c_void; use std::ptr::NonNull; use super::{sync, GroupId, RemoteGroup, RemoteProject, RemoteUser}; @@ -10,7 +10,7 @@ use crate::enterprise; use crate::progress::{NoProgressCallback, ProgressCallback}; use crate::project::Project; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; #[repr(transparent)] pub struct Remote { @@ -27,14 +27,9 @@ impl Remote { } /// Create a Remote and add it to the list of known remotes (saved to Settings) - pub fn new(name: N, address: A) -> Ref { - let name = name.into_bytes_with_nul(); - let address = address.into_bytes_with_nul(); + pub fn new(name: N, address: A) -> Ref { let result = unsafe { - BNCollaborationCreateRemote( - name.as_ref().as_ptr() as *const c_char, - address.as_ref().as_ptr() as *const c_char, - ) + BNCollaborationCreateRemote(name.as_cstr().as_ptr(), address.as_cstr().as_ptr()) }; unsafe { Self::ref_from_raw(NonNull::new(result).unwrap()) } } @@ -168,18 +163,16 @@ impl Remote { } /// Requests an authentication token using a username and password. - pub fn request_authentication_token( + pub fn request_authentication_token( &self, username: U, password: P, ) -> Option { - let username = username.into_bytes_with_nul(); - let password = password.into_bytes_with_nul(); let token = unsafe { BNRemoteRequestAuthenticationToken( self.handle.as_ptr(), - username.as_ref().as_ptr() as *const c_char, - password.as_ref().as_ptr() as *const c_char, + username.as_cstr().as_ptr(), + password.as_cstr().as_ptr(), ) }; if token.is_null() { @@ -229,11 +222,13 @@ impl Remote { token.unwrap().to_string() } }; - let username = options.username.into_bytes_with_nul(); - let username_ptr = username.as_ptr() as *const c_char; - let token = token.into_bytes_with_nul(); - let token_ptr = token.as_ptr() as *const c_char; - let success = unsafe { BNRemoteConnect(self.handle.as_ptr(), username_ptr, token_ptr) }; + let success = unsafe { + BNRemoteConnect( + self.handle.as_ptr(), + options.username.as_cstr().as_ptr(), + token.as_cstr().as_ptr(), + ) + }; success.then_some(()).ok_or(()) } @@ -281,25 +276,19 @@ impl Remote { /// Gets a specific project in the Remote by its id. /// /// NOTE: If projects have not been pulled, they will be pulled upon calling this. - pub fn get_project_by_id( - &self, - id: S, - ) -> Result>, ()> { + pub fn get_project_by_id(&self, id: S) -> Result>, ()> { if !self.has_pulled_projects() { self.pull_projects()?; } - let id = id.into_bytes_with_nul(); - let value = unsafe { - BNRemoteGetProjectById(self.handle.as_ptr(), id.as_ref().as_ptr() as *const c_char) - }; + let value = unsafe { BNRemoteGetProjectById(self.handle.as_ptr(), id.as_cstr().as_ptr()) }; Ok(NonNull::new(value).map(|handle| unsafe { RemoteProject::ref_from_raw(handle) })) } /// Gets a specific project in the Remote by its name. /// /// NOTE: If projects have not been pulled, they will be pulled upon calling this. - pub fn get_project_by_name( + pub fn get_project_by_name( &self, name: S, ) -> Result>, ()> { @@ -307,13 +296,8 @@ impl Remote { self.pull_projects()?; } - let name = name.into_bytes_with_nul(); - let value = unsafe { - BNRemoteGetProjectByName( - self.handle.as_ptr(), - name.as_ref().as_ptr() as *const c_char, - ) - }; + let value = + unsafe { BNRemoteGetProjectByName(self.handle.as_ptr(), name.as_cstr().as_ptr()) }; Ok(NonNull::new(value).map(|handle| unsafe { RemoteProject::ref_from_raw(handle) })) } @@ -347,7 +331,7 @@ impl Remote { /// /// * `name` - Project name /// * `description` - Project description - pub fn create_project( + pub fn create_project( &self, name: N, description: D, @@ -358,13 +342,11 @@ impl Remote { if !self.has_pulled_projects() { self.pull_projects()?; } - let name = name.into_bytes_with_nul(); - let description = description.into_bytes_with_nul(); let value = unsafe { BNRemoteCreateProject( self.handle.as_ptr(), - name.as_ref().as_ptr() as *const c_char, - description.as_ref().as_ptr() as *const c_char, + name.as_cstr().as_ptr(), + description.as_cstr().as_ptr(), ) }; NonNull::new(value) @@ -403,21 +385,16 @@ impl Remote { pub fn push_project(&self, project: &RemoteProject, extra_fields: I) -> Result<(), ()> where I: Iterator, - K: BnStrCompatible, - V: BnStrCompatible, + K: AsCStr, + V: AsCStr, { - let (keys, values): (Vec<_>, Vec<_>) = extra_fields - .into_iter() - .map(|(k, v)| (k.into_bytes_with_nul(), v.into_bytes_with_nul())) - .unzip(); - let mut keys_raw = keys - .iter() - .map(|s| s.as_ref().as_ptr() as *const c_char) - .collect::>(); - let mut values_raw = values - .iter() - .map(|s| s.as_ref().as_ptr() as *const c_char) - .collect::>(); + let (keys, values): (Vec<_>, Vec<_>) = extra_fields.into_iter().unzip(); + + let keys = keys.iter().map(|k| k.as_cstr()).collect::>(); + let mut keys_raw = keys.iter().map(|s| s.as_ptr()).collect::>(); + + let values = values.iter().map(|v| v.as_cstr()).collect::>(); + let mut values_raw = values.iter().map(|v| v.as_ptr()).collect::>(); let success = unsafe { BNRemotePushProject( @@ -472,21 +449,13 @@ impl Remote { /// /// If groups have not been pulled, they will be pulled upon calling this. /// This function is only available to accounts with admin status on the Remote. - pub fn get_group_by_name( - &self, - name: S, - ) -> Result>, ()> { + pub fn get_group_by_name(&self, name: S) -> Result>, ()> { if !self.has_pulled_groups() { self.pull_groups()?; } - let name = name.into_bytes_with_nul(); - let value = unsafe { - BNRemoteGetGroupByName( - self.handle.as_ptr(), - name.as_ref().as_ptr() as *const c_char, - ) - }; + let value = + unsafe { BNRemoteGetGroupByName(self.handle.as_ptr(), name.as_cstr().as_ptr()) }; Ok(NonNull::new(value).map(|handle| unsafe { RemoteGroup::ref_from_raw(handle) })) } @@ -496,11 +465,10 @@ impl Remote { /// # Arguments /// /// * `prefix` - Prefix of name for groups - pub fn search_groups( + pub fn search_groups( &self, prefix: S, ) -> Result<(Array, Array), ()> { - let prefix = prefix.into_bytes_with_nul(); let mut count = 0; let mut group_ids = std::ptr::null_mut(); let mut group_names = std::ptr::null_mut(); @@ -508,7 +476,7 @@ impl Remote { let success = unsafe { BNRemoteSearchGroups( self.handle.as_ptr(), - prefix.as_ref().as_ptr() as *const c_char, + prefix.as_cstr().as_ptr(), &mut group_ids, &mut group_names, &mut count, @@ -560,24 +528,18 @@ impl Remote { /// * `usernames` - List of usernames of users in the group pub fn create_group(&self, name: N, usernames: I) -> Result, ()> where - N: BnStrCompatible, + N: AsCStr, I: IntoIterator, - I::Item: BnStrCompatible, + I::Item: AsCStr, { - let name = name.into_bytes_with_nul(); - let usernames: Vec<_> = usernames - .into_iter() - .map(|s| s.into_bytes_with_nul()) - .collect(); - let mut username_ptrs: Vec<_> = usernames - .iter() - .map(|s| s.as_ref().as_ptr() as *const c_char) - .collect(); + let usernames = usernames.into_iter().collect::>(); + let usernames = usernames.iter().map(|s| s.as_cstr()).collect::>(); + let mut username_ptrs = usernames.iter().map(|s| s.as_ptr()).collect::>(); let value = unsafe { BNRemoteCreateGroup( self.handle.as_ptr(), - name.as_ref().as_ptr() as *const c_char, + name.as_cstr().as_ptr(), username_ptrs.as_mut_ptr(), username_ptrs.len(), ) @@ -597,21 +559,16 @@ impl Remote { pub fn push_group(&self, group: &RemoteGroup, extra_fields: I) -> Result<(), ()> where I: IntoIterator, - K: BnStrCompatible, - V: BnStrCompatible, + K: AsCStr, + V: AsCStr, { - let (keys, values): (Vec<_>, Vec<_>) = extra_fields - .into_iter() - .map(|(k, v)| (k.into_bytes_with_nul(), v.into_bytes_with_nul())) - .unzip(); - let mut keys_raw: Vec<_> = keys - .iter() - .map(|s| s.as_ref().as_ptr() as *const c_char) - .collect(); - let mut values_raw: Vec<_> = values - .iter() - .map(|s| s.as_ref().as_ptr() as *const c_char) - .collect(); + let (keys, values): (Vec<_>, Vec<_>) = extra_fields.into_iter().unzip(); + + let keys = keys.iter().map(|k| k.as_cstr()).collect::>(); + let mut keys_raw = keys.iter().map(|s| s.as_ptr()).collect::>(); + + let values = values.iter().map(|v| v.as_cstr()).collect::>(); + let mut values_raw = values.iter().map(|v| v.as_ptr()).collect::>(); let success = unsafe { BNRemotePushGroup( @@ -663,14 +620,11 @@ impl Remote { /// # Arguments /// /// * `id` - The identifier of the user to retrieve. - pub fn get_user_by_id(&self, id: S) -> Result>, ()> { + pub fn get_user_by_id(&self, id: S) -> Result>, ()> { if !self.has_pulled_users() { self.pull_users()?; } - let id = id.into_bytes_with_nul(); - let value = unsafe { - BNRemoteGetUserById(self.handle.as_ptr(), id.as_ref().as_ptr() as *const c_char) - }; + let value = unsafe { BNRemoteGetUserById(self.handle.as_ptr(), id.as_cstr().as_ptr()) }; Ok(NonNull::new(value).map(|handle| unsafe { RemoteUser::ref_from_raw(handle) })) } @@ -683,20 +637,15 @@ impl Remote { /// # Arguments /// /// * `username` - The username of the user to retrieve. - pub fn get_user_by_username( + pub fn get_user_by_username( &self, username: S, ) -> Result>, ()> { if !self.has_pulled_users() { self.pull_users()?; } - let username = username.into_bytes_with_nul(); - let value = unsafe { - BNRemoteGetUserByUsername( - self.handle.as_ptr(), - username.as_ref().as_ptr() as *const c_char, - ) - }; + let value = + unsafe { BNRemoteGetUserByUsername(self.handle.as_ptr(), username.as_cstr().as_ptr()) }; Ok(NonNull::new(value).map(|handle| unsafe { RemoteUser::ref_from_raw(handle) })) } @@ -718,18 +667,17 @@ impl Remote { /// # Arguments /// /// * `prefix` - The prefix to search for in usernames. - pub fn search_users( + pub fn search_users( &self, prefix: S, ) -> Result<(Array, Array), ()> { - let prefix = prefix.into_bytes_with_nul(); let mut count = 0; let mut user_ids = std::ptr::null_mut(); let mut usernames = std::ptr::null_mut(); let success = unsafe { BNRemoteSearchUsers( self.handle.as_ptr(), - prefix.as_ref().as_ptr() as *const c_char, + prefix.as_cstr().as_ptr(), &mut user_ids, &mut usernames, &mut count, @@ -783,7 +731,7 @@ impl Remote { /// # Arguments /// /// * Various details about the new user to be created. - pub fn create_user( + pub fn create_user( &self, username: U, email: E, @@ -792,17 +740,13 @@ impl Remote { group_ids: &[u64], user_permission_ids: &[u64], ) -> Result, ()> { - let username = username.into_bytes_with_nul(); - let email = email.into_bytes_with_nul(); - let password = password.into_bytes_with_nul(); - let value = unsafe { BNRemoteCreateUser( self.handle.as_ptr(), - username.as_ref().as_ptr() as *const c_char, - email.as_ref().as_ptr() as *const c_char, + username.as_cstr().as_ptr(), + email.as_cstr().as_ptr(), is_active, - password.as_ref().as_ptr() as *const c_char, + password.as_cstr().as_ptr(), group_ids.as_ptr(), group_ids.len(), user_permission_ids.as_ptr(), @@ -825,21 +769,17 @@ impl Remote { pub fn push_user(&self, user: &RemoteUser, extra_fields: I) -> Result<(), ()> where I: Iterator, - K: BnStrCompatible, - V: BnStrCompatible, + K: AsCStr, + V: AsCStr, { - let (keys, values): (Vec<_>, Vec<_>) = extra_fields - .into_iter() - .map(|(k, v)| (k.into_bytes_with_nul(), v.into_bytes_with_nul())) - .unzip(); - let mut keys_raw: Vec<_> = keys - .iter() - .map(|s| s.as_ref().as_ptr() as *const c_char) - .collect(); - let mut values_raw: Vec<_> = values - .iter() - .map(|s| s.as_ref().as_ptr() as *const c_char) - .collect(); + let (keys, values): (Vec<_>, Vec<_>) = extra_fields.into_iter().unzip(); + + let keys = keys.iter().map(|k| k.as_cstr()).collect::>(); + let mut keys_raw = keys.iter().map(|s| s.as_ptr()).collect::>(); + + let values = values.iter().map(|v| v.as_cstr()).collect::>(); + let mut values_raw = values.iter().map(|v| v.as_ptr()).collect::>(); + let success = unsafe { BNRemotePushUser( self.handle.as_ptr(), diff --git a/rust/src/collaboration/snapshot.rs b/rust/src/collaboration/snapshot.rs index 9f8f36934..faa97a25a 100644 --- a/rust/src/collaboration/snapshot.rs +++ b/rust/src/collaboration/snapshot.rs @@ -1,4 +1,4 @@ -use std::ffi::{c_char, c_void}; +use std::ffi::c_void; use std::ptr::NonNull; use std::time::SystemTime; @@ -8,7 +8,7 @@ use crate::collaboration::undo::{RemoteUndoEntry, RemoteUndoEntryId}; use crate::database::snapshot::Snapshot; use crate::progress::{NoProgressCallback, ProgressCallback}; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; use binaryninjacore_sys::*; // TODO: RemoteSnapshotId ? @@ -226,18 +226,17 @@ impl RemoteSnapshot { } /// Create a new Undo Entry in this snapshot. - pub fn create_undo_entry( + pub fn create_undo_entry( &self, parent: Option, data: S, ) -> Result, ()> { - let data = data.into_bytes_with_nul(); let value = unsafe { BNCollaborationSnapshotCreateUndoEntry( self.handle.as_ptr(), parent.is_some(), parent.unwrap_or(0), - data.as_ref().as_ptr() as *const c_char, + data.as_cstr().as_ptr(), ) }; let handle = NonNull::new(value).ok_or(())?; diff --git a/rust/src/collaboration/sync.rs b/rust/src/collaboration/sync.rs index 1c11b8f06..8971f2f5b 100644 --- a/rust/src/collaboration/sync.rs +++ b/rust/src/collaboration/sync.rs @@ -12,7 +12,7 @@ use crate::file_metadata::FileMetadata; use crate::progress::{NoProgressCallback, ProgressCallback}; use crate::project::file::ProjectFile; use crate::rc::Ref; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; use crate::type_archive::{TypeArchive, TypeArchiveMergeConflict}; // TODO: PathBuf @@ -44,10 +44,7 @@ pub fn default_file_path(file: &RemoteFile) -> Result { /// /// * `file` - Remote File to download and open /// * `db_path` - File path for saved database -pub fn download_file( - file: &RemoteFile, - db_path: S, -) -> Result, ()> { +pub fn download_file(file: &RemoteFile, db_path: S) -> Result, ()> { download_file_with_progress(file, db_path, NoProgressCallback) } @@ -58,16 +55,15 @@ pub fn download_file( /// * `file` - Remote File to download and open /// * `db_path` - File path for saved database /// * `progress` - Function to call for progress updates -pub fn download_file_with_progress( +pub fn download_file_with_progress( file: &RemoteFile, db_path: S, mut progress: F, ) -> Result, ()> { - let db_path = db_path.into_bytes_with_nul(); let result = unsafe { BNCollaborationDownloadFile( file.handle.as_ptr(), - db_path.as_ref().as_ptr() as *const c_char, + db_path.as_cstr().as_ptr(), Some(F::cb_progress_callback), &mut progress as *mut F as *mut c_void, ) @@ -222,10 +218,7 @@ pub fn get_local_snapshot_for_remote( .ok_or(()) } -pub fn download_database(file: &RemoteFile, location: S, force: bool) -> Result<(), ()> -where - S: BnStrCompatible, -{ +pub fn download_database(file: &RemoteFile, location: S, force: bool) -> Result<(), ()> { download_database_with_progress(file, location, force, NoProgressCallback) } @@ -236,14 +229,13 @@ pub fn download_database_with_progress( mut progress: F, ) -> Result<(), ()> where - S: BnStrCompatible, + S: AsCStr, F: ProgressCallback, { - let db_path = location.into_bytes_with_nul(); let success = unsafe { BNCollaborationDownloadDatabaseForFile( file.handle.as_ptr(), - db_path.as_ref().as_ptr() as *const c_char, + location.as_cstr().as_ptr(), force, Some(F::cb_progress_callback), &mut progress as *mut _ as *mut c_void, @@ -479,17 +471,16 @@ pub fn get_snapshot_author( /// * `database` - Parent database /// * `snapshot` - Snapshot to edit /// * `author` - Target author -pub fn set_snapshot_author( +pub fn set_snapshot_author( database: &Database, snapshot: &Snapshot, author: S, ) -> Result<(), ()> { - let author = author.into_bytes_with_nul(); let success = unsafe { BNCollaborationSetSnapshotAuthor( database.handle.as_ptr(), snapshot.handle.as_ptr(), - author.as_ref().as_ptr() as *const c_char, + author.as_cstr().as_ptr(), ) }; success.then_some(()).ok_or(()) @@ -654,15 +645,14 @@ pub fn get_remote_file_for_local_type_archive(database: &TypeArchive) -> Option< } /// Get the remote snapshot associated with a local snapshot (if it exists) in a Type Archive -pub fn get_remote_snapshot_from_local_type_archive( +pub fn get_remote_snapshot_from_local_type_archive( type_archive: &TypeArchive, snapshot_id: S, ) -> Option> { - let snapshot_id = snapshot_id.into_bytes_with_nul(); let value = unsafe { BNCollaborationGetRemoteSnapshotFromLocalTypeArchive( type_archive.handle.as_ptr(), - snapshot_id.as_ref().as_ptr() as *const c_char, + snapshot_id.as_cstr().as_ptr(), ) }; NonNull::new(value).map(|handle| unsafe { RemoteSnapshot::ref_from_raw(handle) }) @@ -683,22 +673,21 @@ pub fn get_local_snapshot_from_remote_type_archive( } /// Test if a snapshot is ignored from the archive -pub fn is_type_archive_snapshot_ignored( +pub fn is_type_archive_snapshot_ignored( type_archive: &TypeArchive, snapshot_id: S, ) -> bool { - let snapshot_id = snapshot_id.into_bytes_with_nul(); unsafe { BNCollaborationIsTypeArchiveSnapshotIgnored( type_archive.handle.as_ptr(), - snapshot_id.as_ref().as_ptr() as *const c_char, + snapshot_id.as_cstr().as_ptr(), ) } } /// Download a type archive from its remote, saving all snapshots to an archive in the /// specified `location`. Returns a [`TypeArchive`] for using later. -pub fn download_type_archive( +pub fn download_type_archive( file: &RemoteFile, location: S, ) -> Result>, ()> { @@ -707,17 +696,16 @@ pub fn download_type_archive( /// Download a type archive from its remote, saving all snapshots to an archive in the /// specified `location`. Returns a [`TypeArchive`] for using later. -pub fn download_type_archive_with_progress( +pub fn download_type_archive_with_progress( file: &RemoteFile, location: S, mut progress: F, ) -> Result>, ()> { let mut value = std::ptr::null_mut(); - let db_path = location.into_bytes_with_nul(); let success = unsafe { BNCollaborationDownloadTypeArchive( file.handle.as_ptr(), - db_path.as_ref().as_ptr() as *const c_char, + location.as_cstr().as_ptr(), Some(F::cb_progress_callback), &mut progress as *mut F as *mut c_void, &mut value, diff --git a/rust/src/collaboration/user.rs b/rust/src/collaboration/user.rs index 0e3433d31..779aef28d 100644 --- a/rust/src/collaboration/user.rs +++ b/rust/src/collaboration/user.rs @@ -1,10 +1,9 @@ use super::Remote; use binaryninjacore_sys::*; -use std::ffi::c_char; use std::ptr::NonNull; use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; #[repr(transparent)] pub struct RemoteUser { @@ -49,13 +48,9 @@ impl RemoteUser { } /// Set user's username. You will need to push the user to update the Remote - pub fn set_username(&self, username: U) -> Result<(), ()> { - let username = username.into_bytes_with_nul(); + pub fn set_username(&self, username: U) -> Result<(), ()> { let result = unsafe { - BNCollaborationUserSetUsername( - self.handle.as_ptr(), - username.as_ref().as_ptr() as *const c_char, - ) + BNCollaborationUserSetUsername(self.handle.as_ptr(), username.as_cstr().as_ptr()) }; if result { Ok(()) @@ -72,14 +67,9 @@ impl RemoteUser { } /// Set user's email. You will need to push the user to update the Remote - pub fn set_email(&self, email: U) -> Result<(), ()> { - let username = email.into_bytes_with_nul(); - let result = unsafe { - BNCollaborationUserSetEmail( - self.handle.as_ptr(), - username.as_ref().as_ptr() as *const c_char, - ) - }; + pub fn set_email(&self, email: U) -> Result<(), ()> { + let result = + unsafe { BNCollaborationUserSetEmail(self.handle.as_ptr(), email.as_cstr().as_ptr()) }; if result { Ok(()) } else { diff --git a/rust/src/command.rs b/rust/src/command.rs index 4695d17ed..e246b0668 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_command] for example usage. pub trait Command: 'static + Sync { @@ -95,7 +95,7 @@ where /// ``` pub fn register_command(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_command_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_command_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_command_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 497c1f572..4e0fa90e1 100644 --- a/rust/src/component.rs +++ b/rust/src/component.rs @@ -1,9 +1,8 @@ use crate::binary_view::{BinaryView, BinaryViewExt}; use crate::function::Function; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; use crate::types::ComponentReferencedType; -use std::ffi::c_char; use std::fmt::Debug; use std::ptr::NonNull; @@ -38,29 +37,19 @@ impl ComponentBuilder { pub fn finalize(self) -> Ref { let result = match (&self.parent, &self.name) { (None, None) => unsafe { BNCreateComponent(self.view.handle) }, - (None, Some(name)) => { - let name_raw = name.into_bytes_with_nul(); - unsafe { - BNCreateComponentWithName(self.view.handle, name_raw.as_ptr() as *mut c_char) - } - } - (Some(guid), None) => { - let guid_raw = guid.into_bytes_with_nul(); - unsafe { - BNCreateComponentWithParent(self.view.handle, guid_raw.as_ptr() as *mut c_char) - } - } - (Some(guid), Some(name)) => { - let guid_raw = guid.into_bytes_with_nul(); - let name_raw = name.into_bytes_with_nul(); - unsafe { - BNCreateComponentWithParentAndName( - self.view.handle, - guid_raw.as_ptr() as *mut c_char, - name_raw.as_ptr() as *mut c_char, - ) - } - } + (None, Some(name)) => unsafe { + BNCreateComponentWithName(self.view.handle, name.as_cstr().as_ptr()) + }, + (Some(guid), None) => unsafe { + BNCreateComponentWithParent(self.view.handle, guid.as_cstr().as_ptr()) + }, + (Some(guid), Some(name)) => unsafe { + BNCreateComponentWithParentAndName( + self.view.handle, + guid.as_cstr().as_ptr(), + name.as_cstr().as_ptr(), + ) + }, }; unsafe { Component::ref_from_raw(NonNull::new(result).unwrap()) } } @@ -164,14 +153,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.handle.as_ptr(), - name.as_ref().as_ptr() as *const c_char, - ) - } + pub fn set_name(&self, name: S) { + unsafe { BNComponentSetName(self.handle.as_ptr(), name.as_cstr().as_ptr()) } } /// The component that contains this component, if it exists. @@ -321,7 +304,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 eb95acb2d..d44cf3b47 100644 --- a/rust/src/custom_binary_view.rs +++ b/rust/src/custom_binary_view.rs @@ -41,7 +41,7 @@ use crate::Endianness; /// 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 @@ -359,9 +357,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 7174ebe8f..981f47fd7 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::{NoProgressCallback, ProgressCallback}; use crate::rc::{Array, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; pub struct Database { pub(crate) 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, @@ -90,12 +90,9 @@ impl Database { mut progress: P, ) -> SnapshotId where - N: BnStrCompatible, + N: AsCStr, P: ProgressCallback, { - let name_raw = name.into_bytes_with_nul(); - let name_ptr = name_raw.as_ref().as_ptr() as *const c_char; - let new_id = unsafe { BNWriteDatabaseSnapshotData( self.handle.as_ptr(), @@ -103,7 +100,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, &mut progress as *mut P as *mut c_void, @@ -133,10 +130,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 +151,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 35b0dc46d..a3b3aa5cf 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::ProgressCallback; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; use binaryninjacore_sys::{ BNCollaborationFreeSnapshotIdList, BNFreeSnapshot, BNFreeSnapshotList, BNGetSnapshotChildren, BNGetSnapshotDatabase, BNGetSnapshotFileContents, BNGetSnapshotFileContentsHash, @@ -14,7 +14,7 @@ use binaryninjacore_sys::{ BNReadSnapshotDataWithProgress, BNSetSnapshotName, 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; @@ -50,10 +50,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 11d5f2495..726f7a6bc 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(()) @@ -209,7 +208,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 @@ -259,13 +258,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 _, @@ -417,17 +414,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() @@ -455,17 +445,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) @@ -495,19 +478,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 { @@ -537,15 +514,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() { @@ -555,19 +529,17 @@ 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 mut dv = BNDataVariableAndName::default(); unsafe { if 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(), &mut dv, ) { Some(NamedDataVariableWithType::from_owned_raw(dv)) @@ -577,17 +549,16 @@ 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 mut dv = BNDataVariableAndName::default(); unsafe { if BNGetDebugDataVariableByAddress( self.handle, - parser_name.as_ref().as_ptr() as *mut _, + parser_name.as_cstr().as_ptr(), address, &mut dv, ) { @@ -599,12 +570,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) }; @@ -619,15 +588,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] = @@ -674,96 +638,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(), ) } @@ -771,50 +692,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, @@ -824,18 +731,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 @@ -843,43 +750,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/disassembly.rs b/rust/src/disassembly.rs index 94f76f968..ec1231c94 100644 --- a/rust/src/disassembly.rs +++ b/rust/src/disassembly.rs @@ -22,7 +22,7 @@ use crate::function::{Location, NativeBlock}; use crate::high_level_il as hlil; use crate::low_level_il as llil; use crate::medium_level_il as mlil; -use crate::string::BnStrCompatible; +use crate::string::AsCStr; use crate::string::{raw_to_string, strings_to_string_list, BnString}; use crate::rc::*; @@ -1247,7 +1247,7 @@ impl DisassemblyTextRenderer { unsafe { Array::new(tokens, count, ()) } } - pub fn wrap_comment( + pub fn wrap_comment( &self, cur_line: DisassemblyTextLine, comment: S1, @@ -1256,19 +1256,16 @@ impl DisassemblyTextRenderer { indent_spaces: S3, ) -> Array { let cur_line_raw = DisassemblyTextLine::into_raw(cur_line); - let comment_raw = comment.into_bytes_with_nul(); - let leading_spaces_raw = leading_spaces.into_bytes_with_nul(); - let indent_spaces_raw = indent_spaces.into_bytes_with_nul(); let mut count = 0; let lines = unsafe { BNDisassemblyTextRendererWrapComment( self.handle.as_ptr(), &cur_line_raw, &mut count, - comment_raw.as_ref().as_ptr() as *const ffi::c_char, + comment.as_cstr().as_ptr(), has_auto_annotations, - leading_spaces_raw.as_ref().as_ptr() as *const ffi::c_char, - indent_spaces_raw.as_ref().as_ptr() as *const ffi::c_char, + leading_spaces.as_cstr().as_ptr(), + indent_spaces.as_cstr().as_ptr(), ) }; DisassemblyTextLine::free_raw(cur_line_raw); 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 ad682aadf..bd9cd8ee3 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::ffi::c_void; use std::marker::PhantomData; use std::time::{Duration, SystemTime, UNIX_EPOCH}; @@ -104,13 +104,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 { @@ -163,25 +158,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 fbbadcda6..8d8ba819b 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, @@ -215,18 +199,17 @@ impl FileMetadata { return false; }; - let file_path = file_path.as_ref().into_bytes_with_nul(); unsafe { BNCreateDatabase( raw_view.handle, - file_path.as_ptr() as *mut _, + file_path.as_ref().as_cstr().as_ptr(), ptr::null_mut(), ) } } // TODO: Pass settings? - pub fn create_database_with_progress( + pub fn create_database_with_progress( &self, file_path: impl AsRef, mut progress: P, @@ -235,11 +218,10 @@ impl FileMetadata { let Some(raw_view) = self.view_of_type("Raw") else { return false; }; - let file_path = file_path.as_ref().into_bytes_with_nul(); unsafe { BNCreateDatabaseWithProgress( raw_view.handle, - file_path.as_ptr() as *mut _, + file_path.as_ref().as_cstr().as_ptr(), &mut progress as *mut P as *mut c_void, Some(P::cb_progress_callback), ptr::null_mut(), @@ -256,14 +238,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(()) @@ -273,11 +253,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(()) @@ -286,18 +263,15 @@ impl FileMetadata { } } - pub fn open_database_with_progress( + pub fn open_database_with_progress( &self, filename: S, mut progress: P, ) -> Result, ()> { - let filename = filename.into_bytes_with_nul(); - let filename_ptr = filename.as_ref().as_ptr() as *mut _; - let view = unsafe { BNOpenExistingDatabaseWithProgress( self.handle, - filename_ptr, + filename.as_cstr().as_ptr(), &mut progress as *mut P as *mut c_void, Some(P::cb_progress_callback), ) diff --git a/rust/src/function.rs b/rust/src/function.rs index 66f71e5fe..0ae1d5402 100644 --- a/rust/src/function.rs +++ b/rust/src/function.rs @@ -372,12 +372,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) { @@ -394,12 +390,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 @@ -1101,7 +1093,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, @@ -1698,20 +1690,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 340b85a75..3a1bbbed7 100644 --- a/rust/src/high_level_il/operation.rs +++ b/rust/src/high_level_il/operation.rs @@ -1,12 +1,11 @@ use binaryninjacore_sys::*; -use core::ffi; use std::fmt::{Debug, Formatter}; 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, PartialEq, Eq)] @@ -20,14 +19,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()) } } } @@ -327,7 +321,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 924ccbfea..3dc8bf61f 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -102,7 +102,7 @@ use std::cmp; 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; @@ -128,13 +128,11 @@ pub fn load_with_progress( file_path: impl AsRef, mut progress: P, ) -> Option> { - let file_path = file_path.as_ref().into_bytes_with_nul(); - let options = c""; 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(P::cb_progress_callback), &mut progress as *mut P as *mut c_void, ) @@ -193,25 +191,18 @@ where O: IntoJson, P: ProgressCallback, { - 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 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(P::cb_progress_callback), &mut progress as *mut P as *mut c_void, ) @@ -247,23 +238,17 @@ where P: ProgressCallback, { 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 handle = unsafe { BNLoadBinaryView( bv.handle as *mut _, update_analysis_and_wait, - options_or_default.as_ptr() as *mut c_char, + options_or_default.as_ptr(), Some(P::cb_progress_callback), &mut progress as *mut P as *mut c_void, ) @@ -292,8 +277,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 { @@ -334,9 +318,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(()); } @@ -344,9 +326,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(()); } @@ -354,9 +334,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(()); } @@ -479,9 +457,8 @@ impl VersionInfo { let _ = unsafe { BnString::from_raw(value.channel) }; } - pub fn from_string(string: S) -> Self { - let string = string.into_bytes_with_nul(); - let result = unsafe { BNParseVersionString(string.as_ref().as_ptr() as *const c_char) }; + pub fn from_string(string: S) -> Self { + let result = unsafe { BNParseVersionString(string.as_cstr().as_ptr()) }; Self::from_owned_raw(result) } } @@ -538,14 +515,12 @@ pub fn license_count() -> i32 { /// 1. Check the BN_LICENSE environment variable /// 2. Check the Binary Ninja user directory for license.dat #[cfg(not(feature = "demo"))] -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()) } } #[cfg(feature = "demo")] -pub fn set_license(_license: Option) {} +pub fn set_license(_license: Option) {} pub fn product() -> BnString { unsafe { BnString::from_raw(BNGetProduct()) } @@ -564,10 +539,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 { @@ -594,16 +567,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 5cc0b58b5..873312268 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}; @@ -122,20 +121,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(), ) } } @@ -144,7 +142,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, @@ -153,13 +151,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, ) } @@ -274,21 +271,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(), ) } } @@ -297,7 +292,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, @@ -306,14 +301,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 cdbaf25dc..3bde59cf7 100644 --- a/rust/src/platform.rs +++ b/rust/src/platform.rs @@ -82,10 +82,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 @@ -113,27 +112,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, ); @@ -151,10 +143,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 }) } @@ -179,25 +170,18 @@ impl Platform { unsafe { TypeContainer::from_raw(type_container_ptr.unwrap()) } } - 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); } } @@ -278,15 +262,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, @@ -317,22 +298,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(), ) }; @@ -360,20 +337,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 fad1e5ef2..c34950455 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::{NoProgressCallback, ProgressCallback}; 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 { pub(crate) 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, parent, description, NoProgressCallback) } @@ -196,20 +163,18 @@ impl Project { mut progress: PC, ) -> Result, ()> where - P: BnStrCompatible, - D: BnStrCompatible, + P: AsCStr, + D: AsCStr, PC: ProgressCallback, { - 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()); 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(), &mut progress as *mut PC as *mut c_void, Some(PC::cb_progress_callback), ); @@ -229,18 +194,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(())?)) } @@ -260,21 +223,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(())?)) } @@ -292,10 +252,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) }) } @@ -350,9 +308,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, @@ -379,23 +337,20 @@ impl Project { mut progress: PC, ) -> Result, ()> where - P: BnStrCompatible, - N: BnStrCompatible, - D: BnStrCompatible, + P: AsCStr, + N: AsCStr, + D: AsCStr, PC: ProgressCallback, { - 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()); 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(), &mut progress as *mut PC as *mut c_void, Some(PC::cb_progress_callback), ); @@ -421,10 +376,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, @@ -458,26 +413,22 @@ impl Project { mut progress: PC, ) -> Result, ()> where - P: BnStrCompatible, - N: BnStrCompatible, - D: BnStrCompatible, - I: BnStrCompatible, + P: AsCStr, + N: AsCStr, + D: AsCStr, + I: AsCStr, PC: ProgressCallback, { - 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()); 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(), &mut progress as *mut PC as *mut c_void, Some(PC::cb_progress_callback), @@ -500,8 +451,8 @@ impl Project { description: D, ) -> Result, ()> where - N: BnStrCompatible, - D: BnStrCompatible, + N: AsCStr, + D: AsCStr, { self.create_file_with_progress(contents, folder, name, description, NoProgressCallback) } @@ -522,12 +473,10 @@ impl Project { mut progress: P, ) -> Result, ()> where - N: BnStrCompatible, - D: BnStrCompatible, + N: AsCStr, + D: AsCStr, P: ProgressCallback, { - 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()); unsafe { @@ -536,8 +485,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(), &mut progress as *mut P as *mut c_void, Some(P::cb_progress_callback), ); @@ -563,9 +512,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, @@ -599,14 +548,11 @@ impl Project { mut progress: P, ) -> Result, ()> where - N: BnStrCompatible, - D: BnStrCompatible, - I: BnStrCompatible, + N: AsCStr, + D: AsCStr, + I: AsCStr, P: ProgressCallback, { - 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()); unsafe { @@ -615,9 +561,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(), &mut progress as *mut P as *mut c_void, Some(P::cb_progress_callback), @@ -635,21 +581,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 90b40051b..9282737bf 100644 --- a/rust/src/project/folder.rs +++ b/rust/src/project/folder.rs @@ -1,14 +1,14 @@ use crate::progress::{NoProgressCallback, ProgressCallback}; 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, NoProgressCallback) } @@ -99,15 +87,13 @@ impl ProjectFolder { /// * `progress` - [`ProgressCallback`] that will be called as contents are exporting pub fn export_with_progress(&self, dest: S, mut progress: P) -> bool where - S: BnStrCompatible, + S: AsCStr, P: ProgressCallback, { - let dest_raw = dest.into_bytes_with_nul(); - let success = unsafe { BNProjectFolderExport( self.handle.as_ptr(), - dest_raw.as_ref().as_ptr() as *const c_char, + dest.as_cstr().as_ptr(), &mut progress as *mut P as *mut c_void, Some(P::cb_progress_callback), ) 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/render_layer.rs b/rust/src/render_layer.rs index 80ecc6394..411c3eb26 100644 --- a/rust/src/render_layer.rs +++ b/rust/src/render_layer.rs @@ -6,9 +6,9 @@ use crate::flowgraph::FlowGraph; use crate::function::{Function, NativeBlock}; use crate::linear_view::{LinearDisassemblyLine, LinearDisassemblyLineType, LinearViewObject}; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner}; -use crate::string::BnStrCompatible; +use crate::string::AsCStr; use binaryninjacore_sys::*; -use std::ffi::{c_char, c_void}; +use std::ffi::c_void; use std::ptr::NonNull; /// The state in which the [`RenderLayer`] will be registered with. @@ -61,7 +61,7 @@ impl Default for RenderLayerDefaultState { } /// Register a [`RenderLayer`] with the API. -pub fn register_render_layer( +pub fn register_render_layer( name: S, render_layer: T, default_state: RenderLayerDefaultState, @@ -74,11 +74,7 @@ pub fn register_render_layer( freeLines: Some(cb_free_lines), }; let result = unsafe { - BNRegisterRenderLayer( - name.into_bytes_with_nul().as_ref().as_ptr() as *const _, - &mut callback, - default_state.into(), - ) + BNRegisterRenderLayer(name.as_cstr().as_ptr(), &mut callback, default_state.into()) }; let core = CoreRenderLayer::from_raw(NonNull::new(result).unwrap()); (render_layer, core) @@ -303,9 +299,8 @@ impl CoreRenderLayer { unsafe { Array::new(result, count, ()) } } - pub fn render_layer_by_name(name: S) -> Option { - let name_raw = name.into_bytes_with_nul(); - let result = unsafe { BNGetRenderLayerByName(name_raw.as_ref().as_ptr() as *const c_char) }; + pub fn render_layer_by_name(name: S) -> Option { + let result = unsafe { BNGetRenderLayerByName(name.as_cstr().as_ptr()) }; NonNull::new(result).map(Self::from_raw) } diff --git a/rust/src/repository.rs b/rust/src/repository.rs index 135b23678..c2ea66800 100644 --- a/rust/src/repository.rs +++ b/rust/src/repository.rs @@ -9,7 +9,7 @@ use binaryninjacore_sys::*; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; use crate::repository::plugin::RepositoryPlugin; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; pub use manager::RepositoryManager; @@ -52,14 +52,9 @@ impl Repository { unsafe { Array::new(result, count, ()) } } - pub fn plugin_by_path(&self, path: S) -> Option> { - let path = path.into_bytes_with_nul(); - let result = unsafe { - BNRepositoryGetPluginByPath( - self.handle.as_ptr(), - path.as_ref().as_ptr() as *const c_char, - ) - }; + pub fn plugin_by_path(&self, path: S) -> Option> { + let result = + unsafe { BNRepositoryGetPluginByPath(self.handle.as_ptr(), path.as_cstr().as_ptr()) }; NonNull::new(result).map(|h| unsafe { RepositoryPlugin::ref_from_raw(h) }) } diff --git a/rust/src/repository/manager.rs b/rust/src/repository/manager.rs index 598891625..aac7042e1 100644 --- a/rust/src/repository/manager.rs +++ b/rust/src/repository/manager.rs @@ -1,13 +1,12 @@ use crate::rc::{Array, Ref, RefCountable}; use crate::repository::Repository; -use crate::string::BnStrCompatible; +use crate::string::AsCStr; use binaryninjacore_sys::{ BNCreateRepositoryManager, BNFreeRepositoryManager, BNGetRepositoryManager, BNNewRepositoryManagerReference, BNRepositoryGetRepositoryByPath, BNRepositoryManager, BNRepositoryManagerAddRepository, BNRepositoryManagerCheckForUpdates, BNRepositoryManagerGetDefaultRepository, BNRepositoryManagerGetRepositories, }; -use std::ffi::c_char; use std::fmt::Debug; use std::ptr::NonNull; @@ -29,10 +28,8 @@ impl RepositoryManager { Ref::new(Self { handle }) } - pub fn new(plugins_path: S) -> Ref { - let plugins_path = plugins_path.into_bytes_with_nul(); - let result = - unsafe { BNCreateRepositoryManager(plugins_path.as_ref().as_ptr() as *const c_char) }; + pub fn new(plugins_path: S) -> Ref { + let result = unsafe { BNCreateRepositoryManager(plugins_path.as_cstr().as_ptr()) }; unsafe { Self::ref_from_raw(NonNull::new(result).unwrap()) } } @@ -61,29 +58,19 @@ impl RepositoryManager { /// * `repository_path` - path to where the repository will be stored on disk locally /// /// Returns true if the repository was successfully added, false otherwise. - pub fn add_repository( - &self, - url: U, - repository_path: P, - ) -> bool { - let url = url.into_bytes_with_nul(); - let repo_path = repository_path.into_bytes_with_nul(); + pub fn add_repository(&self, url: U, repository_path: P) -> bool { unsafe { BNRepositoryManagerAddRepository( self.handle.as_ptr(), - url.as_ref().as_ptr() as *const c_char, - repo_path.as_ref().as_ptr() as *const c_char, + url.as_cstr().as_ptr(), + repository_path.as_cstr().as_ptr(), ) } } - pub fn repository_by_path(&self, path: P) -> Option { - let path = path.into_bytes_with_nul(); + pub fn repository_by_path(&self, path: P) -> Option { let result = unsafe { - BNRepositoryGetRepositoryByPath( - self.handle.as_ptr(), - path.as_ref().as_ptr() as *const c_char, - ) + BNRepositoryGetRepositoryByPath(self.handle.as_ptr(), path.as_cstr().as_ptr()) }; NonNull::new(result).map(|raw| unsafe { Repository::from_raw(raw) }) } diff --git a/rust/src/secrets_provider.rs b/rust/src/secrets_provider.rs index e61cd4665..cd328517e 100644 --- a/rust/src/secrets_provider.rs +++ b/rust/src/secrets_provider.rs @@ -4,7 +4,7 @@ use std::fmt::Debug; use std::ptr::NonNull; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; pub trait SecretsProvider { fn has_data(&mut self, key: &str) -> bool; @@ -27,7 +27,6 @@ impl CoreSecretsProvider { /// Register a new provider pub fn new(name: &str, callback: C) -> Self { // SAFETY: once create SecretsProvider is never dropped - let name = name.into_bytes_with_nul(); let callback = Box::leak(Box::new(callback)); let mut callbacks = BNSecretsProviderCallbacks { context: callback as *mut C as *mut c_void, @@ -36,8 +35,7 @@ impl CoreSecretsProvider { storeData: Some(cb_store_data::), deleteData: Some(cb_delete_data::), }; - let result = - unsafe { BNRegisterSecretsProvider(name.as_ptr() as *const c_char, &mut callbacks) }; + let result = unsafe { BNRegisterSecretsProvider(name.as_cstr().as_ptr(), &mut callbacks) }; unsafe { Self::from_raw(NonNull::new(result).unwrap()) } } @@ -50,9 +48,8 @@ impl CoreSecretsProvider { } /// Retrieve a provider by name - pub fn by_name(name: S) -> Option { - let name = name.into_bytes_with_nul(); - let result = unsafe { BNGetSecretsProviderByName(name.as_ref().as_ptr() as *const c_char) }; + pub fn by_name(name: S) -> Option { + let result = unsafe { BNGetSecretsProviderByName(name.as_cstr().as_ptr()) }; NonNull::new(result).map(|h| unsafe { Self::from_raw(h) }) } @@ -63,44 +60,31 @@ impl CoreSecretsProvider { } /// Check if data for a specific key exists, but do not retrieve it - pub fn has_data(&self, key: S) -> bool { - let key = key.into_bytes_with_nul(); - unsafe { - BNSecretsProviderHasData(self.handle.as_ptr(), key.as_ref().as_ptr() as *const c_char) - } + pub fn has_data(&self, key: S) -> bool { + unsafe { BNSecretsProviderHasData(self.handle.as_ptr(), key.as_cstr().as_ptr()) } } /// Retrieve data for the given key, if it exists - pub fn get_data(&self, key: S) -> BnString { - let key = key.into_bytes_with_nul(); - let result = unsafe { - BNGetSecretsProviderData(self.handle.as_ptr(), key.as_ref().as_ptr() as *const c_char) - }; + pub fn get_data(&self, key: S) -> BnString { + let result = + unsafe { BNGetSecretsProviderData(self.handle.as_ptr(), key.as_cstr().as_ptr()) }; unsafe { BnString::from_raw(result) } } /// Store data with the given key - pub fn store_data(&self, key: K, value: V) -> bool { - let key = key.into_bytes_with_nul(); - let value = value.into_bytes_with_nul(); + pub fn store_data(&self, key: K, value: V) -> bool { unsafe { BNStoreSecretsProviderData( self.handle.as_ptr(), - key.as_ref().as_ptr() as *const c_char, - value.as_ref().as_ptr() as *const c_char, + key.as_cstr().as_ptr(), + value.as_cstr().as_ptr(), ) } } /// Delete stored data with the given key - pub fn delete_data(&self, key: S) -> bool { - let key = key.into_bytes_with_nul(); - unsafe { - BNDeleteSecretsProviderData( - self.handle.as_ptr(), - key.as_ref().as_ptr() as *const c_char, - ) - } + pub fn delete_data(&self, key: S) -> bool { + unsafe { BNDeleteSecretsProviderData(self.handle.as_ptr(), key.as_cstr().as_ptr()) } } } diff --git a/rust/src/section.rs b/rust/src/section.rs index 2c63693d5..dc7181a52 100644 --- a/rust/src/section.rs +++ b/rust/src/section.rs @@ -14,7 +14,6 @@ //! Sections are [crate::segment::Segment]s that are loaded into memory at run time -use std::ffi::c_char; use std::fmt; use std::ops::Range; @@ -270,44 +269,29 @@ impl SectionBuilder { } pub(crate) fn create(self, view: &BinaryView) { - let name = self.name.into_bytes_with_nul(); - let ty = self.ty.into_bytes_with_nul(); - let linked_section = self.linked_section.into_bytes_with_nul(); - let info_section = self.info_section.into_bytes_with_nul(); - let start = self.range.start; let len = self.range.end.wrapping_sub(start); + let add_section = if self.is_auto { + BNAddAutoSection + } else { + BNAddUserSection + }; + unsafe { - if self.is_auto { - BNAddAutoSection( - view.handle, - name.as_ptr() as *const c_char, - start, - len, - self.semantics.into(), - ty.as_ptr() as *const c_char, - self.align, - self.entry_size, - linked_section.as_ptr() as *const c_char, - info_section.as_ptr() as *const c_char, - self.info_data, - ); - } else { - BNAddUserSection( - view.handle, - name.as_ptr() as *const c_char, - start, - len, - self.semantics.into(), - ty.as_ptr() as *const c_char, - self.align, - self.entry_size, - linked_section.as_ptr() as *const c_char, - info_section.as_ptr() as *const c_char, - self.info_data, - ); - } + add_section( + view.handle, + self.name.as_cstr().as_ptr(), + start, + len, + self.semantics.into(), + self.ty.as_cstr().as_ptr(), + self.align, + self.entry_size, + self.linked_section.as_cstr().as_ptr(), + self.info_section.as_cstr().as_ptr(), + self.info_data, + ) } } } diff --git a/rust/src/settings.rs b/rust/src/settings.rs index a2deef574..e3f356b1b 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 3bda6a81f..c12f33c99 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,28 +69,32 @@ 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 { @@ -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()) + self.as_c_str().to_string_lossy().fmt(f) } } impl fmt::Debug for BnString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.to_string_lossy().fmt(f) + self.as_c_str().to_string_lossy().fmt(f) } } @@ -186,111 +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 { - let ret = CString::new(self.as_os_str().as_encoded_bytes()) - .expect("can't pass paths with internal nul bytes to core!"); - ret.into_bytes_with_nul() +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 9c29af177..f44523c08 100644 --- a/rust/src/symbol.rs +++ b/rust/src/symbol.rs @@ -153,64 +153,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 3b20bc045..7a62f9e87 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 f10cda504..c37b10f85 100644 --- a/rust/src/type_archive.rs +++ b/rust/src/type_archive.rs @@ -10,7 +10,7 @@ use crate::data_buffer::DataBuffer; use crate::metadata::Metadata; use crate::platform::Platform; 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,17 +773,14 @@ impl TypeArchive { mut progress: P, ) -> Result> where - B: BnStrCompatible, - F: BnStrCompatible, - S: BnStrCompatible, + B: AsCStr, + F: AsCStr, + S: AsCStr, M: IntoIterator, - MI: BnStrCompatible, - MK: BnStrCompatible, + MI: AsCStr, + MK: AsCStr, P: ProgressCallback, { - 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(), @@ -1168,14 +1124,8 @@ impl TypeArchiveMergeConflict { } // TODO: This needs documentation! - pub fn success(&self, value: S) -> bool { - let value = value.into_bytes_with_nul(); - unsafe { - BNTypeArchiveMergeConflictSuccess( - self.handle.as_ptr(), - value.as_ref().as_ptr() as *const c_char, - ) - } + pub fn success(&self, value: S) -> bool { + unsafe { BNTypeArchiveMergeConflictSuccess(self.handle.as_ptr(), value.as_cstr().as_ptr()) } } } diff --git a/rust/src/type_container.rs b/rust/src/type_container.rs index 947c6912a..a397a04ec 100644 --- a/rust/src/type_container.rs +++ b/rust/src/type_container.rs @@ -11,12 +11,12 @@ use crate::platform::Platform; use crate::progress::{NoProgressCallback, ProgressCallback}; 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; @@ -137,19 +137,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 @@ -159,14 +150,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. @@ -184,13 +169,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, ) }; @@ -200,13 +184,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, ) }; @@ -305,19 +288,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, @@ -351,46 +333,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 35db62ff3..d70ee7ff1 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -24,7 +24,7 @@ use crate::{ binary_view::{BinaryView, BinaryViewExt}, calling_convention::CoreCallingConvention, 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 { @@ -1216,26 +1186,21 @@ impl EnumerationBuilder { unsafe { Enumeration::ref_from_raw(BNFinalizeEnumerationBuilder(self.handle)) } } - pub fn append(&mut self, name: S) -> &mut Self { - let name = name.into_bytes_with_nul(); - unsafe { - BNAddEnumerationBuilderMember(self.handle, name.as_ref().as_ptr() as _); - } + pub fn append(&mut self, name: S) -> &mut Self { + unsafe { BNAddEnumerationBuilderMember(self.handle, name.as_cstr().as_ptr()) } self } - pub fn insert(&mut self, name: S, value: u64) -> &mut Self { - let name = name.into_bytes_with_nul(); + pub fn insert(&mut self, name: S, value: u64) -> &mut 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(&mut self, id: usize, name: S, value: u64) -> &mut Self { - let name = name.into_bytes_with_nul(); + pub fn replace(&mut self, id: usize, name: S, value: u64) -> &mut Self { unsafe { - BNReplaceEnumerationBuilderMember(self.handle, id, name.as_ref().as_ptr() as _, value); + BNReplaceEnumerationBuilderMember(self.handle, id, name.as_cstr().as_ptr(), value) } self } @@ -1475,20 +1440,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, ); @@ -1512,7 +1476,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, @@ -1521,13 +1485,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, @@ -1537,21 +1500,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, ) } @@ -1869,17 +1831,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/websocket/client.rs b/rust/src/websocket/client.rs index 36c7bedd2..0480e229a 100644 --- a/rust/src/websocket/client.rs +++ b/rust/src/websocket/client.rs @@ -1,5 +1,5 @@ use crate::rc::{Ref, RefCountable}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; use binaryninjacore_sys::*; use std::ffi::{c_char, c_void, CStr}; use std::ptr::NonNull; @@ -21,8 +21,8 @@ pub trait WebsocketClient: Sync + Send { fn connect(&self, host: &str, headers: I) -> bool where I: IntoIterator, - K: BnStrCompatible, - V: BnStrCompatible; + K: AsCStr, + V: AsCStr; fn write(&self, data: &[u8]) -> bool; @@ -77,23 +77,17 @@ impl CoreWebsocketClient { ) -> bool where I: IntoIterator, - K: BnStrCompatible, - V: BnStrCompatible, + K: AsCStr, + V: AsCStr, C: WebsocketClientCallback, { - let url = host.into_bytes_with_nul(); - let (header_keys, header_values): (Vec, Vec) = headers - .into_iter() - .map(|(k, v)| (k.into_bytes_with_nul(), v.into_bytes_with_nul())) - .unzip(); - let header_keys: Vec<*const c_char> = header_keys - .iter() - .map(|k| k.as_ref().as_ptr() as *const c_char) - .collect(); - let header_values: Vec<*const c_char> = header_values + let headers = headers.into_iter().collect::>(); + let (header_keys, header_values): (Vec<_>, Vec<_>) = headers .iter() - .map(|v| v.as_ref().as_ptr() as *const c_char) - .collect(); + .map(|(k, v)| (k.as_cstr(), v.as_cstr())) + .unzip(); + let header_keys: Vec<_> = header_keys.iter().map(|k| k.as_ptr()).collect(); + let header_values: Vec<_> = header_values.iter().map(|v| v.as_ptr()).collect(); // SAFETY: This context will only be live for the duration of BNConnectWebsocketClient // SAFETY: Any subsequent call to BNConnectWebsocketClient will write over the context. let mut output_callbacks = BNWebsocketClientOutputCallbacks { @@ -106,7 +100,7 @@ impl CoreWebsocketClient { unsafe { BNConnectWebsocketClient( self.handle.as_ptr(), - url.as_ptr() as *const c_char, + host.as_cstr().as_ptr(), header_keys.len().try_into().unwrap(), header_keys.as_ptr(), header_values.as_ptr(), @@ -129,10 +123,7 @@ impl CoreWebsocketClient { /// Call the error callback function pub fn notify_error(&self, msg: &str) { - let error = msg.into_bytes_with_nul(); - unsafe { - BNNotifyWebsocketClientError(self.handle.as_ptr(), error.as_ptr() as *const c_char) - } + unsafe { BNNotifyWebsocketClientError(self.handle.as_ptr(), msg.as_cstr().as_ptr()) } } /// Call the read callback function, forward the callback returned value @@ -195,8 +186,8 @@ pub(crate) unsafe extern "C" fn cb_connect( let header_count = usize::try_from(header_count).unwrap(); let header_keys = core::slice::from_raw_parts(header_keys as *const BnString, header_count); let header_values = core::slice::from_raw_parts(header_values as *const BnString, header_count); - let header_keys_str = header_keys.iter().map(|s| s.to_string_lossy()); - let header_values_str = header_values.iter().map(|s| s.to_string_lossy()); + let header_keys_str = header_keys.iter().map(|s| s.to_string()); + let header_values_str = header_values.iter().map(|s| s.to_string()); let header = header_keys_str.zip(header_values_str); ctxt.connect(&host.to_string_lossy(), header) } diff --git a/rust/src/websocket/provider.rs b/rust/src/websocket/provider.rs index 0e28afe45..a12a50ba1 100644 --- a/rust/src/websocket/provider.rs +++ b/rust/src/websocket/provider.rs @@ -1,9 +1,9 @@ use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref}; -use crate::string::{BnStrCompatible, BnString}; +use crate::string::{AsCStr, BnString}; use crate::websocket::client; use crate::websocket::client::{CoreWebsocketClient, WebsocketClient}; use binaryninjacore_sys::*; -use std::ffi::{c_char, c_void}; +use std::ffi::c_void; use std::mem::MaybeUninit; use std::ptr::NonNull; @@ -11,13 +11,12 @@ pub fn register_websocket_provider(name: &str) -> &'static mut W where W: WebsocketProvider, { - let name = name.into_bytes_with_nul(); let provider_uninit = MaybeUninit::uninit(); // SAFETY: Websocket provider is never freed let leaked_provider = Box::leak(Box::new(provider_uninit)); let result = unsafe { BNRegisterWebsocketProvider( - name.as_ptr() as *const c_char, + name.as_cstr().as_ptr(), &mut BNWebsocketProviderCallbacks { context: leaked_provider as *mut _ as *mut c_void, createClient: Some(cb_create_client::), @@ -80,10 +79,8 @@ impl CoreWebsocketProvider { unsafe { Array::new(result, count, ()) } } - pub fn by_name(name: S) -> Option { - let name = name.into_bytes_with_nul(); - let result = - unsafe { BNGetWebsocketProviderByName(name.as_ref().as_ptr() as *const c_char) }; + pub fn by_name(name: S) -> Option { + let result = unsafe { BNGetWebsocketProviderByName(name.as_cstr().as_ptr()) }; NonNull::new(result).map(|h| unsafe { Self::from_raw(h) }) } 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 dcc388d91..abc180f8a 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(), ) @@ -535,22 +480,17 @@ impl Workflow { /// * `activities` - the list of Activities to insert pub fn insert_after(&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 { BNWorkflowInsertAfter( 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(), ) @@ -558,29 +498,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(), ) } } @@ -589,17 +520,16 @@ 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( + 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, ) }; diff --git a/rust/tests/websocket.rs b/rust/tests/websocket.rs index 97a4ae2ba..01d2d7912 100644 --- a/rust/tests/websocket.rs +++ b/rust/tests/websocket.rs @@ -1,6 +1,6 @@ use binaryninja::headless::Session; use binaryninja::rc::Ref; -use binaryninja::string::BnStrCompatible; +use binaryninja::string::AsCStr; use binaryninja::websocket::{ register_websocket_provider, CoreWebsocketClient, CoreWebsocketProvider, WebsocketClient, WebsocketClientCallback, WebsocketProvider, @@ -34,8 +34,8 @@ impl WebsocketClient for MyWebsocketClient { fn connect(&self, host: &str, _headers: I) -> bool where I: IntoIterator, - K: BnStrCompatible, - V: BnStrCompatible, + K: AsCStr, + V: AsCStr, { assert_eq!(host, "url"); true