diff options
| author | Mason Reed <mason@vector35.com> | 2025-05-03 23:15:17 -0400 |
|---|---|---|
| committer | Mason Reed <35282038+emesare@users.noreply.github.com> | 2025-05-12 17:45:24 -0400 |
| commit | 6264254065bbae9d89f51cf3330379b7ace09592 (patch) | |
| tree | 9ece1d1739215c2faef2d808ef4fdc019ad527fa | |
| parent | c3fdda9727f5507818e3f55576ad32215a22b0f9 (diff) | |
[Rust] Return `String` instead of `BnString` for cases where lossy conversion can be tolerated
Still need to go and audit all usage, but realistically the most important places to give the user control are with symbols, where the data can come from non utf8 sources
This is still incomplete, I just looked for usage of -> BnString so any other variant was omitted.
61 files changed, 381 insertions, 398 deletions
diff --git a/plugins/dwarf/dwarf_export/src/lib.rs b/plugins/dwarf/dwarf_export/src/lib.rs index bc159825..d1754d29 100644 --- a/plugins/dwarf/dwarf_export/src/lib.rs +++ b/plugins/dwarf/dwarf_export/src/lib.rs @@ -18,7 +18,6 @@ use binaryninja::{ interaction, interaction::{FormResponses, FormResponses::Index}, rc::Ref, - string::BnString, symbol::SymbolType, types::{MemberAccess, StructureType, Type, TypeClass}, }; @@ -422,7 +421,7 @@ fn export_functions( // Set subprogram DIE attributes dwarf.unit.get_mut(function_die_uid).set( gimli::DW_AT_name, - AttributeValue::String(function.symbol().short_name().as_bytes().to_vec()), + AttributeValue::String(function.symbol().short_name().to_bytes().to_vec()), ); // TODO : (DW_AT_main_subprogram VS DW_TAG_entry_point) @@ -557,7 +556,7 @@ fn export_data_vars( if let Some(symbol) = data_var_sym { dwarf.unit.get_mut(var_die_uid).set( gimli::DW_AT_name, - AttributeValue::String(symbol.full_name().as_bytes().to_vec()), + AttributeValue::String(symbol.full_name().to_bytes().to_vec()), ); if symbol.external() { @@ -756,7 +755,7 @@ fn export_dwarf(bv: &BinaryView) { let arch_name = if let Some(arch) = bv.default_arch() { arch.name() } else { - BnString::new("Unknown") + String::from("Unknown") }; let responses = present_form(arch_name.as_str()); diff --git a/plugins/dwarf/shared/src/lib.rs b/plugins/dwarf/shared/src/lib.rs index b12aeab1..c4ed7937 100644 --- a/plugins/dwarf/shared/src/lib.rs +++ b/plugins/dwarf/shared/src/lib.rs @@ -106,7 +106,7 @@ pub fn create_section_reader<'a, Endian: 'a + Endianity>( if let Some(symbol) = view .symbols() .iter() - .find(|symbol| symbol.full_name().as_str() == "__elf_section_headers") + .find(|symbol| symbol.full_name().to_string_lossy() == "__elf_section_headers") { if let Some(data_var) = view .data_variables() diff --git a/plugins/warp/src/bin/sigem.rs b/plugins/warp/src/bin/sigem.rs index a455f1e8..a50b4ae2 100644 --- a/plugins/warp/src/bin/sigem.rs +++ b/plugins/warp/src/bin/sigem.rs @@ -131,7 +131,7 @@ fn main() { fn data_from_view(view: &BinaryView) -> Data { let mut data = Data::default(); let is_function_named = |f: &BNGuard<BNFunction>| { - !f.symbol().short_name().as_str().contains("sub_") || f.has_user_annotations() + !f.symbol().short_name().to_string_lossy().contains("sub_") || f.has_user_annotations() }; data.functions = view diff --git a/plugins/warp/src/cache.rs b/plugins/warp/src/cache.rs index 7219b547..8c82c687 100644 --- a/plugins/warp/src/cache.rs +++ b/plugins/warp/src/cache.rs @@ -439,7 +439,7 @@ pub struct TypeRefID(u64); impl From<&BNNamedTypeReference> for TypeRefID { fn from(value: &BNNamedTypeReference) -> Self { let mut hasher = DefaultHasher::new(); - hasher.write(value.id().as_bytes()); + hasher.write(value.id().to_bytes()); Self(hasher.finish()) } } diff --git a/plugins/warp/src/matcher.rs b/plugins/warp/src/matcher.rs index 81458f8d..6352cd7a 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/plugins/warp/src/plugin/create.rs b/plugins/warp/src/plugin/create.rs index 4beba195..e84e42ad 100644 --- a/plugins/warp/src/plugin/create.rs +++ b/plugins/warp/src/plugin/create.rs @@ -18,7 +18,7 @@ pub struct CreateSignatureFile; impl Command for CreateSignatureFile { fn action(&self, view: &BinaryView) { let is_function_named = |f: &Guard<Function>| { - !f.symbol().short_name().as_str().contains("sub_") || f.has_user_annotations() + !f.symbol().short_name().to_string_lossy().contains("sub_") || f.has_user_annotations() }; let mut signature_dir = user_signature_dir(); if let Some(default_plat) = view.default_platform() { diff --git a/rust/src/architecture.rs b/rust/src/architecture.rs index c0fe138e..d2e5e0fc 100644 --- a/rust/src/architecture.rs +++ b/rust/src/architecture.rs @@ -1412,8 +1412,8 @@ impl CoreArchitecture { } } - pub fn name(&self) -> BnString { - unsafe { BnString::from_raw(BNGetArchitectureName(self.handle)) } + pub fn name(&self) -> String { + unsafe { BnString::into_string(BNGetArchitectureName(self.handle)) } } } diff --git a/rust/src/background_task.rs b/rust/src/background_task.rs index c818d5b9..5d30f27d 100644 --- a/rust/src/background_task.rs +++ b/rust/src/background_task.rs @@ -71,8 +71,8 @@ impl BackgroundTask { unsafe { BNFinishBackgroundTask(self.handle) } } - pub fn progress_text(&self) -> BnString { - unsafe { BnString::from_raw(BNGetBackgroundTaskProgressText(self.handle)) } + pub fn progress_text(&self) -> String { + unsafe { BnString::into_string(BNGetBackgroundTaskProgressText(self.handle)) } } pub fn set_progress_text<S: BnStrCompatible>(&self, text: S) { diff --git a/rust/src/base_detection.rs b/rust/src/base_detection.rs index 1fd45ef6..c74f3f3a 100644 --- a/rust/src/base_detection.rs +++ b/rust/src/base_detection.rs @@ -174,9 +174,9 @@ impl BaseAddressDetectionSettings { let arch_name = value .arch .map(|a| a.name().as_ptr()) - .unwrap_or(BASE_ADDRESS_AUTO_DETECTION_ARCH.as_ptr() as *const c_char); + .unwrap_or(BASE_ADDRESS_AUTO_DETECTION_ARCH.as_ptr() as *const u8); BNBaseAddressDetectionSettings { - Architecture: arch_name, + Architecture: arch_name as *const c_char, Analysis: value.analysis.as_raw().as_ptr(), MinStrlen: value.min_string_len, Alignment: value.alignment.get(), diff --git a/rust/src/binary_view.rs b/rust/src/binary_view.rs index db4c92d7..d8f35caf 100644 --- a/rust/src/binary_view.rs +++ b/rust/src/binary_view.rs @@ -27,7 +27,7 @@ use crate::architecture::{Architecture, CoreArchitecture}; use crate::base_detection::BaseAddressDetection; use crate::basic_block::BasicBlock; use crate::binary_view::memory_map::MemoryMap; -use crate::component::{Component, IntoComponentGuid}; +use crate::component::Component; use crate::confidence::Conf; use crate::data_buffer::DataBuffer; use crate::debuginfo::DebugInfo; @@ -187,9 +187,9 @@ pub trait BinaryViewExt: BinaryViewBase { } } - fn type_name(&self) -> BnString { + fn type_name(&self) -> String { let ptr: *mut c_char = unsafe { BNGetViewType(self.as_ref().handle) }; - unsafe { BnString::from_raw(ptr) } + unsafe { BnString::into_string(ptr) } } fn parent_view(&self) -> Option<Ref<BinaryView>> { @@ -204,9 +204,9 @@ pub trait BinaryViewExt: BinaryViewBase { self.file().view_of_type("Raw") } - fn view_type(&self) -> BnString { + fn view_type(&self) -> String { let ptr: *mut c_char = unsafe { BNGetViewType(self.as_ref().handle) }; - unsafe { BnString::from_raw(ptr) } + unsafe { BnString::into_string(ptr) } } /// Reads up to `len` bytes from address `offset` @@ -1493,9 +1493,14 @@ pub trait BinaryViewExt: BinaryViewBase { unsafe { BNRemoveComponent(self.as_ref().handle, component.handle.as_ptr()) } } - fn remove_component_by_guid<P: IntoComponentGuid>(&self, guid: P) -> bool { - let path = guid.component_guid(); - unsafe { BNRemoveComponentByGuid(self.as_ref().handle, path.as_ptr()) } + fn remove_component_by_guid<P: BnStrCompatible>(&self, guid: P) -> bool { + let path = guid.into_bytes_with_nul(); + unsafe { + BNRemoveComponentByGuid( + self.as_ref().handle, + path.as_ref().as_ptr() as *const c_char, + ) + } } fn data_variable_parent_components(&self, data_variable: &DataVariable) -> Array<Component> { diff --git a/rust/src/binary_view/memory_map.rs b/rust/src/binary_view/memory_map.rs index 3e248c54..182cb16a 100644 --- a/rust/src/binary_view/memory_map.rs +++ b/rust/src/binary_view/memory_map.rs @@ -108,10 +108,10 @@ impl MemoryMap { } } - pub fn active_memory_region_at(&self, addr: u64) -> BnString { + pub fn active_memory_region_at(&self, addr: u64) -> String { unsafe { let name_raw = BNGetActiveMemoryRegionAt(self.view.handle, addr); - BnString::from_raw(name_raw) + BnString::into_string(name_raw) } } diff --git a/rust/src/calling_convention.rs b/rust/src/calling_convention.rs index 2fb282e0..6f2e9a1c 100644 --- a/rust/src/calling_convention.rs +++ b/rust/src/calling_convention.rs @@ -455,8 +455,8 @@ impl CoreCallingConvention { }) } - pub fn name(&self) -> BnString { - unsafe { BnString::from_raw(BNGetCallingConventionName(self.handle)) } + pub fn name(&self) -> String { + unsafe { BnString::into_string(BNGetCallingConventionName(self.handle)) } } pub fn variables_for_parameters( diff --git a/rust/src/collaboration/changeset.rs b/rust/src/collaboration/changeset.rs index 9d7cdb7c..fd862df6 100644 --- a/rust/src/collaboration/changeset.rs +++ b/rust/src/collaboration/changeset.rs @@ -59,10 +59,10 @@ impl Changeset { } /// Changeset name - pub fn name(&self) -> BnString { + pub fn name(&self) -> String { let result = unsafe { BNCollaborationChangesetGetName(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Set the name of the changeset, e.g. in a name changeset function. diff --git a/rust/src/collaboration/file.rs b/rust/src/collaboration/file.rs index 2651d3c7..678c0c15 100644 --- a/rust/src/collaboration/file.rs +++ b/rust/src/collaboration/file.rs @@ -106,30 +106,30 @@ impl RemoteFile { } /// Web API endpoint URL - pub fn url(&self) -> BnString { + pub fn url(&self) -> String { let result = unsafe { BNRemoteFileGetUrl(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Chat log API endpoint URL - pub fn chat_log_url(&self) -> BnString { + pub fn chat_log_url(&self) -> String { let result = unsafe { BNRemoteFileGetChatLogUrl(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } - pub fn user_positions_url(&self) -> BnString { + pub fn user_positions_url(&self) -> String { let result = unsafe { BNRemoteFileGetUserPositionsUrl(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Unique ID - pub fn id(&self) -> BnString { + pub fn id(&self) -> String { let result = unsafe { BNRemoteFileGetId(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// All files share the same properties, but files with different types may make different @@ -144,10 +144,10 @@ impl RemoteFile { crate::ffi::time_from_bn(result.try_into().unwrap()) } - pub fn created_by(&self) -> BnString { + pub fn created_by(&self) -> String { let result = unsafe { BNRemoteFileGetCreatedBy(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Last modified of the file @@ -163,30 +163,30 @@ impl RemoteFile { } /// Username of user who pushed the last snapshot in the file - pub fn last_snapshot_by(&self) -> BnString { + pub fn last_snapshot_by(&self) -> String { let result = unsafe { BNRemoteFileGetLastSnapshotBy(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } - pub fn last_snapshot_name(&self) -> BnString { + pub fn last_snapshot_name(&self) -> String { let result = unsafe { BNRemoteFileGetLastSnapshotName(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Hash of file contents (no algorithm guaranteed) - pub fn hash(&self) -> BnString { + pub fn hash(&self) -> String { let result = unsafe { BNRemoteFileGetHash(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Displayed name of file - pub fn name(&self) -> BnString { + pub fn name(&self) -> String { let result = unsafe { BNRemoteFileGetName(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Set the description of the file. You will need to push the file to update the remote version. @@ -202,10 +202,10 @@ impl RemoteFile { } /// Desciprtion of the file - pub fn description(&self) -> BnString { + pub fn description(&self) -> String { let result = unsafe { BNRemoteFileGetDescription(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Set the description of the file. You will need to push the file to update the remote version. @@ -220,10 +220,10 @@ impl RemoteFile { success.then_some(()).ok_or(()) } - pub fn metadata(&self) -> BnString { + pub fn metadata(&self) -> String { let result = unsafe { BNRemoteFileGetMetadata(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Size of raw content of file, in bytes @@ -234,10 +234,10 @@ impl RemoteFile { /// Get the default filepath for a remote File. This is based off the Setting for /// collaboration.directory, the file's id, the file's project's id, and the file's /// remote's id. - pub fn default_path(&self) -> BnString { + pub fn default_path(&self) -> String { let result = unsafe { BNCollaborationDefaultFilePath(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// If the file has pulled the snapshots yet @@ -410,16 +410,16 @@ impl RemoteFile { // todo!() //} - pub fn request_user_positions(&self) -> BnString { + pub fn request_user_positions(&self) -> String { let result = unsafe { BNRemoteFileRequestUserPositions(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } - pub fn request_chat_log(&self) -> BnString { + pub fn request_chat_log(&self) -> String { let result = unsafe { BNRemoteFileRequestChatLog(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } // TODO: AsRef<Path> diff --git a/rust/src/collaboration/folder.rs b/rust/src/collaboration/folder.rs index 90a85f1c..eb4fd9f8 100644 --- a/rust/src/collaboration/folder.rs +++ b/rust/src/collaboration/folder.rs @@ -76,17 +76,17 @@ impl RemoteFolder { } /// Get web API endpoint URL. - pub fn url(&self) -> BnString { + pub fn url(&self) -> String { let result = unsafe { BNRemoteFolderGetUrl(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Get unique ID. - pub fn id(&self) -> BnString { + pub fn id(&self) -> String { let result = unsafe { BNRemoteFolderGetId(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Unique id of parent folder, if there is a parent. None, otherwise @@ -97,10 +97,10 @@ impl RemoteFolder { } /// Displayed name of folder - pub fn name(&self) -> BnString { + pub fn name(&self) -> String { let result = unsafe { BNRemoteFolderGetName(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Set the display name of the folder. You will need to push the folder to update the remote version. @@ -116,10 +116,10 @@ impl RemoteFolder { } /// Description of the folder - pub fn description(&self) -> BnString { + pub fn description(&self) -> String { let result = unsafe { BNRemoteFolderGetDescription(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Set the description of the folder. You will need to push the folder to update the remote version. diff --git a/rust/src/collaboration/group.rs b/rust/src/collaboration/group.rs index bad09d6c..9fb287a7 100644 --- a/rust/src/collaboration/group.rs +++ b/rust/src/collaboration/group.rs @@ -30,10 +30,10 @@ impl RemoteGroup { } /// Web api endpoint url - pub fn url(&self) -> BnString { + pub fn url(&self) -> String { let value = unsafe { BNCollaborationGroupGetUrl(self.handle.as_ptr()) }; assert!(!value.is_null()); - unsafe { BnString::from_raw(value) } + unsafe { BnString::into_string(value) } } /// Unique id @@ -42,10 +42,10 @@ impl RemoteGroup { } /// Group name - pub fn name(&self) -> BnString { + pub fn name(&self) -> String { let value = unsafe { BNCollaborationGroupGetName(self.handle.as_ptr()) }; assert!(!value.is_null()); - unsafe { BnString::from_raw(value) } + unsafe { BnString::into_string(value) } } /// Set group name diff --git a/rust/src/collaboration/merge.rs b/rust/src/collaboration/merge.rs index 2d28725c..68bfdc02 100644 --- a/rust/src/collaboration/merge.rs +++ b/rust/src/collaboration/merge.rs @@ -108,18 +108,18 @@ impl MergeConflict { /// String representing the type name of the data, not the same as data_type. /// This is like "typeName" or "tag" depending on what object the conflict represents. - pub fn conflict_type(&self) -> BnString { + pub fn conflict_type(&self) -> String { let result = unsafe { BNAnalysisMergeConflictGetType(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Lookup key for the merge conflict, ideally a tree path that contains the name of the conflict /// and all the recursive children leading up to this conflict. - pub fn key(&self) -> BnString { + pub fn key(&self) -> String { let result = unsafe { BNAnalysisMergeConflictGetKey(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Call this when you've resolved the conflict to save the result diff --git a/rust/src/collaboration/permission.rs b/rust/src/collaboration/permission.rs index 99a7a4f2..76b1eba3 100644 --- a/rust/src/collaboration/permission.rs +++ b/rust/src/collaboration/permission.rs @@ -37,17 +37,17 @@ impl Permission { } /// Web api endpoint url - pub fn url(&self) -> BnString { + pub fn url(&self) -> String { let value = unsafe { BNCollaborationPermissionGetUrl(self.handle.as_ptr()) }; assert!(!value.is_null()); - unsafe { BnString::from_raw(value) } + unsafe { BnString::into_string(value) } } /// unique id - pub fn id(&self) -> BnString { + pub fn id(&self) -> String { let value = unsafe { BNCollaborationPermissionGetId(self.handle.as_ptr()) }; assert!(!value.is_null()); - unsafe { BnString::from_raw(value) } + unsafe { BnString::into_string(value) } } /// Level of permission diff --git a/rust/src/collaboration/project.rs b/rust/src/collaboration/project.rs index 1455f6c3..b3c6513d 100644 --- a/rust/src/collaboration/project.rs +++ b/rust/src/collaboration/project.rs @@ -103,17 +103,17 @@ impl RemoteProject { } /// Get the URL of the project - pub fn url(&self) -> BnString { + pub fn url(&self) -> String { let result = unsafe { BNRemoteProjectGetUrl(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Get the unique ID of the project - pub fn id(&self) -> BnString { + pub fn id(&self) -> String { let result = unsafe { BNRemoteProjectGetId(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Created date of the project @@ -129,10 +129,10 @@ impl RemoteProject { } /// Displayed name of file - pub fn name(&self) -> BnString { + pub fn name(&self) -> String { let result = unsafe { BNRemoteProjectGetName(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Set the description of the file. You will need to push the file to update the remote version. @@ -148,10 +148,10 @@ impl RemoteProject { } /// Desciprtion of the file - pub fn description(&self) -> BnString { + pub fn description(&self) -> String { let result = unsafe { BNRemoteProjectGetDescription(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Set the description of the file. You will need to push the file to update the remote version. @@ -879,9 +879,9 @@ impl RemoteProject { /// Get the default directory path for a remote Project. This is based off /// the Setting for collaboration.directory, the project's id, and the /// project's remote's id. - pub fn default_project_path(&self) -> BnString { + pub fn default_project_path(&self) -> String { let result = unsafe { BNCollaborationDefaultProjectPath(self.handle.as_ptr()) }; - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Upload a file, with database, to the remote under the given project diff --git a/rust/src/collaboration/remote.rs b/rust/src/collaboration/remote.rs index c1250403..98784ddb 100644 --- a/rust/src/collaboration/remote.rs +++ b/rust/src/collaboration/remote.rs @@ -65,17 +65,17 @@ impl Remote { } /// Gets the name of the remote. - pub fn name(&self) -> BnString { + pub fn name(&self) -> String { let result = unsafe { BNRemoteGetName(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Gets the address of the remote. - pub fn address(&self) -> BnString { + pub fn address(&self) -> String { let result = unsafe { BNRemoteGetAddress(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Checks if the remote is connected. @@ -84,17 +84,17 @@ impl Remote { } /// Gets the username used to connect to the remote. - pub fn username(&self) -> BnString { + pub fn username(&self) -> String { let result = unsafe { BNRemoteGetUsername(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Gets the token used to connect to the remote. - pub fn token(&self) -> BnString { + pub fn token(&self) -> String { let result = unsafe { BNRemoteGetToken(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Gets the server version. If metadata has not been pulled, it will be pulled upon calling this. diff --git a/rust/src/collaboration/snapshot.rs b/rust/src/collaboration/snapshot.rs index 9f8f3693..935b1c2f 100644 --- a/rust/src/collaboration/snapshot.rs +++ b/rust/src/collaboration/snapshot.rs @@ -54,52 +54,52 @@ impl RemoteSnapshot { } /// Web api endpoint url - pub fn url(&self) -> BnString { + pub fn url(&self) -> String { let value = unsafe { BNCollaborationSnapshotGetUrl(self.handle.as_ptr()) }; assert!(!value.is_null()); - unsafe { BnString::from_raw(value) } + unsafe { BnString::into_string(value) } } /// Unique id - pub fn id(&self) -> BnString { + pub fn id(&self) -> String { let value = unsafe { BNCollaborationSnapshotGetId(self.handle.as_ptr()) }; assert!(!value.is_null()); - unsafe { BnString::from_raw(value) } + unsafe { BnString::into_string(value) } } /// Name of snapshot - pub fn name(&self) -> BnString { + pub fn name(&self) -> String { let value = unsafe { BNCollaborationSnapshotGetName(self.handle.as_ptr()) }; assert!(!value.is_null()); - unsafe { BnString::from_raw(value) } + unsafe { BnString::into_string(value) } } /// Get the title of a snapshot: the first line of its name - pub fn title(&self) -> BnString { + pub fn title(&self) -> String { let value = unsafe { BNCollaborationSnapshotGetTitle(self.handle.as_ptr()) }; assert!(!value.is_null()); - unsafe { BnString::from_raw(value) } + unsafe { BnString::into_string(value) } } /// Get the description of a snapshot: the lines of its name after the first line - pub fn description(&self) -> BnString { + pub fn description(&self) -> String { let value = unsafe { BNCollaborationSnapshotGetDescription(self.handle.as_ptr()) }; assert!(!value.is_null()); - unsafe { BnString::from_raw(value) } + unsafe { BnString::into_string(value) } } /// Get the user id of the author of a snapshot - pub fn author(&self) -> BnString { + pub fn author(&self) -> String { let value = unsafe { BNCollaborationSnapshotGetAuthor(self.handle.as_ptr()) }; assert!(!value.is_null()); - unsafe { BnString::from_raw(value) } + unsafe { BnString::into_string(value) } } /// Get the username of the author of a snapshot, if possible (vs author which is user id) - pub fn author_username(&self) -> BnString { + pub fn author_username(&self) -> String { let value = unsafe { BNCollaborationSnapshotGetAuthorUsername(self.handle.as_ptr()) }; assert!(!value.is_null()); - unsafe { BnString::from_raw(value) } + unsafe { BnString::into_string(value) } } /// Created date of Snapshot @@ -116,18 +116,18 @@ impl RemoteSnapshot { /// Hash of snapshot data (analysis and markup, etc) /// No specific hash algorithm is guaranteed - pub fn hash(&self) -> BnString { + pub fn hash(&self) -> String { let value = unsafe { BNCollaborationSnapshotGetHash(self.handle.as_ptr()) }; assert!(!value.is_null()); - unsafe { BnString::from_raw(value) } + unsafe { BnString::into_string(value) } } /// Hash of file contents in snapshot /// No specific hash algorithm is guaranteed - pub fn snapshot_file_hash(&self) -> BnString { + pub fn snapshot_file_hash(&self) -> String { let value = unsafe { BNCollaborationSnapshotGetSnapshotFileHash(self.handle.as_ptr()) }; assert!(!value.is_null()); - unsafe { BnString::from_raw(value) } + unsafe { BnString::into_string(value) } } /// If the snapshot has pulled undo entries yet diff --git a/rust/src/collaboration/sync.rs b/rust/src/collaboration/sync.rs index 1c11b8f0..6fc85d31 100644 --- a/rust/src/collaboration/sync.rs +++ b/rust/src/collaboration/sync.rs @@ -3,7 +3,6 @@ use super::{ }; use binaryninjacore_sys::*; use std::ffi::{c_char, c_void}; -use std::mem::ManuallyDrop; use std::ptr::NonNull; use crate::binary_view::{BinaryView, BinaryViewExt}; @@ -12,7 +11,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::{raw_to_string, BnStrCompatible, BnString}; use crate::type_archive::{TypeArchive, TypeArchiveMergeConflict}; // TODO: PathBuf @@ -859,13 +858,11 @@ pub trait DatabaseConflictHandler: Sized { let keys = core::slice::from_raw_parts(keys, conflict_count); let conflicts = core::slice::from_raw_parts(conflicts, conflict_count); keys.iter().zip(conflicts.iter()).all(|(key, conflict)| { - // NOTE this is a reference, not owned, so ManuallyDrop is required, or just implement `ref_from_raw` - // TODO: Replace with raw_to_string - let key = ManuallyDrop::new(BnString::from_raw(*key as *mut _)); + let key = raw_to_string(*key).unwrap(); // TODO I guess dont drop here? let raw_ptr = NonNull::new(*conflict).unwrap(); let conflict = MergeConflict::from_raw(raw_ptr); - ctxt.handle_conflict(key.as_str(), &conflict) + ctxt.handle_conflict(&key, &conflict) }) } } diff --git a/rust/src/collaboration/undo.rs b/rust/src/collaboration/undo.rs index 9f1cc5f0..0dde860f 100644 --- a/rust/src/collaboration/undo.rs +++ b/rust/src/collaboration/undo.rs @@ -57,10 +57,10 @@ impl RemoteUndoEntry { } /// Web api endpoint url - pub fn url(&self) -> BnString { + pub fn url(&self) -> String { let value = unsafe { BNCollaborationUndoEntryGetUrl(self.handle.as_ptr()) }; assert!(!value.is_null()); - unsafe { BnString::from_raw(value) } + unsafe { BnString::into_string(value) } } /// Unique id diff --git a/rust/src/collaboration/user.rs b/rust/src/collaboration/user.rs index 0e3433d3..b08e9da4 100644 --- a/rust/src/collaboration/user.rs +++ b/rust/src/collaboration/user.rs @@ -28,24 +28,24 @@ impl RemoteUser { } /// Web api endpoint url - pub fn url(&self) -> BnString { + pub fn url(&self) -> String { let value = unsafe { BNCollaborationUserGetUrl(self.handle.as_ptr()) }; assert!(!value.is_null()); - unsafe { BnString::from_raw(value) } + unsafe { BnString::into_string(value) } } /// Unique id - pub fn id(&self) -> BnString { + pub fn id(&self) -> String { let value = unsafe { BNCollaborationUserGetId(self.handle.as_ptr()) }; assert!(!value.is_null()); - unsafe { BnString::from_raw(value) } + unsafe { BnString::into_string(value) } } /// User's login username - pub fn username(&self) -> BnString { + pub fn username(&self) -> String { let value = unsafe { BNCollaborationUserGetUsername(self.handle.as_ptr()) }; assert!(!value.is_null()); - unsafe { BnString::from_raw(value) } + unsafe { BnString::into_string(value) } } /// Set user's username. You will need to push the user to update the Remote @@ -65,10 +65,10 @@ impl RemoteUser { } /// User's email address - pub fn email(&self) -> BnString { + pub fn email(&self) -> String { let value = unsafe { BNCollaborationUserGetEmail(self.handle.as_ptr()) }; assert!(!value.is_null()); - unsafe { BnString::from_raw(value) } + unsafe { BnString::into_string(value) } } /// Set user's email. You will need to push the user to update the Remote @@ -88,10 +88,10 @@ impl RemoteUser { } /// String representing the last date the user logged in - pub fn last_login(&self) -> BnString { + pub fn last_login(&self) -> String { let value = unsafe { BNCollaborationUserGetLastLogin(self.handle.as_ptr()) }; assert!(!value.is_null()); - unsafe { BnString::from_raw(value) } + unsafe { BnString::into_string(value) } } /// If the user account is active and can log in diff --git a/rust/src/component.rs b/rust/src/component.rs index 497c1f57..72441c52 100644 --- a/rust/src/component.rs +++ b/rust/src/component.rs @@ -86,10 +86,10 @@ impl Component { Ref::new(Self { handle }) } - pub fn guid(&self) -> BnString { + pub fn guid(&self) -> String { let result = unsafe { BNComponentGetGuid(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Add function to this component. @@ -145,10 +145,10 @@ impl Component { } /// Original name of the component - pub fn display_name(&self) -> BnString { + pub fn display_name(&self) -> String { let result = unsafe { BNComponentGetDisplayName(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Original name set for this component @@ -158,10 +158,10 @@ impl Component { /// remain what was originally set (e.g. "MyComponentName") /// If this component has a duplicate name and is moved to a component where none of its siblings share its name, /// .name will return the original "MyComponentName" - pub fn name(&self) -> BnString { + pub fn name(&self) -> String { let result = unsafe { BNComponentGetOriginalName(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } pub fn set_name<S: BnStrCompatible>(&self, name: S) { @@ -309,20 +309,3 @@ unsafe impl CoreArrayProviderInner for Component { Guard::new(Self::from_raw(raw_ptr), context) } } - -// TODO: Should we keep this? -pub trait IntoComponentGuid { - fn component_guid(self) -> BnString; -} - -impl IntoComponentGuid for &Component { - fn component_guid(self) -> BnString { - self.guid() - } -} - -impl<S: BnStrCompatible> 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 a43bbd4b..de841a26 100644 --- a/rust/src/custom_binary_view.rs +++ b/rust/src/custom_binary_view.rs @@ -15,6 +15,7 @@ //! An interface for providing your own [BinaryView]s to Binary Ninja. use binaryninjacore_sys::*; +use std::ffi::c_char; pub use binaryninjacore_sys::BNModificationStatus as ModificationStatus; @@ -211,12 +212,12 @@ pub trait BinaryViewTypeBase: AsRef<BinaryViewType> { } pub trait BinaryViewTypeExt: BinaryViewTypeBase { - fn name(&self) -> BnString { - unsafe { BnString::from_raw(BNGetBinaryViewTypeName(self.as_ref().handle)) } + fn name(&self) -> String { + unsafe { BnString::into_string(BNGetBinaryViewTypeName(self.as_ref().handle)) } } - fn long_name(&self) -> BnString { - unsafe { BnString::from_raw(BNGetBinaryViewTypeLongName(self.as_ref().handle)) } + fn long_name(&self) -> String { + unsafe { BnString::into_string(BNGetBinaryViewTypeLongName(self.as_ref().handle)) } } fn register_arch<A: Architecture>(&self, id: u32, endianness: Endianness, arch: &A) { @@ -502,7 +503,7 @@ impl<'a, T: CustomBinaryViewType> CustomViewBuilder<'a, T> { let view_name = view_type.name(); - if let Some(bv) = file.view_of_type(view_name.as_str()) { + if let Some(bv) = file.view_of_type(&view_name) { // while it seems to work most of the time, you can get really unlucky // if the a free of the existing view of the same type kicks off while // BNCreateBinaryViewOfType is still running. the freeObject callback @@ -514,7 +515,7 @@ impl<'a, T: CustomBinaryViewType> CustomViewBuilder<'a, T> { // going to try and stop this from happening in the first place. log::error!( "attempt to create duplicate view of type '{}' (existing: {:?})", - view_name.as_str(), + view_name, bv.handle ); @@ -879,7 +880,7 @@ impl<'a, T: CustomBinaryViewType> CustomViewBuilder<'a, T> { unsafe { let res = BNCreateCustomBinaryView( - view_name.as_ptr(), + view_name.as_ptr() as *const c_char, file.handle, parent.handle, &mut bn_obj, diff --git a/rust/src/data_buffer.rs b/rust/src/data_buffer.rs index 5b7d1ae6..460bb94d 100644 --- a/rust/src/data_buffer.rs +++ b/rust/src/data_buffer.rs @@ -110,9 +110,9 @@ impl DataBuffer { } } - pub fn to_escaped_string(&self, null_terminates: bool, escape_printable: bool) -> BnString { + pub fn to_escaped_string(&self, null_terminates: bool, escape_printable: bool) -> String { unsafe { - BnString::from_raw(BNDataBufferToEscapedString( + BnString::into_string(BNDataBufferToEscapedString( self.0, null_terminates, escape_printable, @@ -124,8 +124,8 @@ impl DataBuffer { Self(unsafe { BNDecodeEscapedString(value.as_ptr()) }) } - pub fn to_base64(&self) -> BnString { - unsafe { BnString::from_raw(BNDataBufferToBase64(self.0)) } + pub fn to_base64(&self) -> String { + unsafe { BnString::into_string(BNDataBufferToBase64(self.0)) } } pub fn from_base64(value: &BnString) -> Self { diff --git a/rust/src/database/snapshot.rs b/rust/src/database/snapshot.rs index 35b0dc46..3768138c 100644 --- a/rust/src/database/snapshot.rs +++ b/rust/src/database/snapshot.rs @@ -45,8 +45,8 @@ impl Snapshot { } /// Get the displayed snapshot name - pub fn name(&self) -> BnString { - unsafe { BnString::from_raw(BNGetSnapshotName(self.handle.as_ptr())) } + pub fn name(&self) -> String { + unsafe { BnString::into_string(BNGetSnapshotName(self.handle.as_ptr())) } } /// Set the displayed snapshot name diff --git a/rust/src/database/undo.rs b/rust/src/database/undo.rs index 727a777b..a2001b72 100644 --- a/rust/src/database/undo.rs +++ b/rust/src/database/undo.rs @@ -26,10 +26,10 @@ impl UndoEntry { Ref::new(Self { handle }) } - pub fn id(&self) -> BnString { + pub fn id(&self) -> String { let result = unsafe { BNUndoEntryGetId(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } pub fn actions(&self) -> Array<UndoAction> { @@ -115,10 +115,10 @@ impl UndoAction { } /// Gets the [`UndoAction`] summary as text rather than [`InstructionTextToken`]'s. - pub fn summary_as_string(&self) -> BnString { + pub fn summary_as_string(&self) -> String { let result = unsafe { BNUndoActionGetSummaryText(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } } diff --git a/rust/src/debuginfo.rs b/rust/src/debuginfo.rs index 1353f8b1..bafa9cc4 100644 --- a/rust/src/debuginfo.rs +++ b/rust/src/debuginfo.rs @@ -141,8 +141,8 @@ impl DebugInfoParser { } /// Returns the name of the current parser - pub fn name(&self) -> BnString { - unsafe { BnString::from_raw(BNGetDebugInfoParserName(self.handle)) } + pub fn name(&self) -> String { + unsafe { BnString::into_string(BNGetDebugInfoParserName(self.handle)) } } /// Returns whether this debug-info parser is valid for the provided binary view diff --git a/rust/src/demangle.rs b/rust/src/demangle.rs index e4d0be1d..bfe65f9a 100644 --- a/rust/src/demangle.rs +++ b/rust/src/demangle.rs @@ -232,8 +232,8 @@ impl Demangler { } } - pub fn name(&self) -> BnString { - unsafe { BnString::from_raw(BNGetDemanglerName(self.handle)) } + pub fn name(&self) -> String { + unsafe { BnString::into_string(BNGetDemanglerName(self.handle)) } } pub fn from_name<S: BnStrCompatible>(name: S) -> Option<Self> { diff --git a/rust/src/disassembly.rs b/rust/src/disassembly.rs index 99a6b22e..6125f623 100644 --- a/rust/src/disassembly.rs +++ b/rust/src/disassembly.rs @@ -302,9 +302,7 @@ impl InstructionTextToken { } pub(crate) fn free_raw(value: BNInstructionTextToken) { - if !value.text.is_null() { - unsafe { BNFreeString(value.text) }; - } + unsafe { BnString::free_raw(value.text) }; if !value.typeNames.is_null() { unsafe { BNFreeStringList(value.typeNames, value.namesCount) }; } diff --git a/rust/src/download_provider.rs b/rust/src/download_provider.rs index 39136c7d..4b7b3c0c 100644 --- a/rust/src/download_provider.rs +++ b/rust/src/download_provider.rs @@ -105,9 +105,9 @@ impl DownloadInstance { Ref::new(Self::from_raw(handle)) } - fn get_error(&self) -> BnString { + fn get_error(&self) -> String { let err: *mut c_char = unsafe { BNGetErrorForDownloadInstance(self.handle) }; - unsafe { BnString::from_raw(err) } + unsafe { BnString::into_string(err) } } unsafe extern "C" fn o_write_callback(data: *mut u8, len: u64, ctxt: *mut c_void) -> u64 { @@ -138,7 +138,7 @@ impl DownloadInstance { &mut self, url: S, callbacks: DownloadInstanceOutputCallbacks, - ) -> Result<(), BnString> { + ) -> Result<(), String> { let callbacks = Box::into_raw(Box::new(callbacks)); let mut cbs = BNDownloadInstanceOutputCallbacks { writeCallback: Some(Self::o_write_callback), @@ -215,7 +215,7 @@ impl DownloadInstance { url: U, headers: I, callbacks: DownloadInstanceInputOutputCallbacks, - ) -> Result<DownloadResponse, BnString> { + ) -> Result<DownloadResponse, String> { let mut header_keys = vec![]; let mut header_values = vec![]; for (key, value) in headers { diff --git a/rust/src/enterprise.rs b/rust/src/enterprise.rs index 7030b194..9b97a387 100644 --- a/rust/src/enterprise.rs +++ b/rust/src/enterprise.rs @@ -98,13 +98,13 @@ pub fn release_license() { } // TODO: If "" string return None -pub fn server_username() -> BnString { - unsafe { BnString::from_raw(binaryninjacore_sys::BNGetEnterpriseServerUsername()) } +pub fn server_username() -> String { + unsafe { BnString::into_string(binaryninjacore_sys::BNGetEnterpriseServerUsername()) } } // TODO: If "" string return None -pub fn server_url() -> BnString { - unsafe { BnString::from_raw(binaryninjacore_sys::BNGetEnterpriseServerUrl()) } +pub fn server_url() -> String { + unsafe { BnString::into_string(binaryninjacore_sys::BNGetEnterpriseServerUrl()) } } pub fn set_server_url<S: BnStrCompatible>(url: S) -> Result<(), ()> { @@ -121,24 +121,24 @@ pub fn set_server_url<S: BnStrCompatible>(url: S) -> Result<(), ()> { } } -pub fn server_name() -> BnString { - unsafe { BnString::from_raw(binaryninjacore_sys::BNGetEnterpriseServerName()) } +pub fn server_name() -> String { + unsafe { BnString::into_string(binaryninjacore_sys::BNGetEnterpriseServerName()) } } -pub fn server_id() -> BnString { - unsafe { BnString::from_raw(binaryninjacore_sys::BNGetEnterpriseServerId()) } +pub fn server_id() -> String { + unsafe { BnString::into_string(binaryninjacore_sys::BNGetEnterpriseServerId()) } } pub fn server_version() -> u64 { unsafe { binaryninjacore_sys::BNGetEnterpriseServerVersion() } } -pub fn server_build_id() -> BnString { - unsafe { BnString::from_raw(binaryninjacore_sys::BNGetEnterpriseServerBuildId()) } +pub fn server_build_id() -> String { + unsafe { BnString::into_string(binaryninjacore_sys::BNGetEnterpriseServerBuildId()) } } -pub fn server_token() -> BnString { - unsafe { BnString::from_raw(binaryninjacore_sys::BNGetEnterpriseServerToken()) } +pub fn server_token() -> String { + unsafe { BnString::into_string(binaryninjacore_sys::BNGetEnterpriseServerToken()) } } pub fn license_duration() -> Duration { @@ -226,8 +226,8 @@ pub fn initialize_server() -> bool { unsafe { binaryninjacore_sys::BNInitializeEnterpriseServer() } } -pub fn server_last_error() -> BnString { - unsafe { BnString::from_raw(binaryninjacore_sys::BNGetEnterpriseServerLastError()) } +pub fn server_last_error() -> String { + unsafe { BnString::into_string(binaryninjacore_sys::BNGetEnterpriseServerLastError()) } } pub fn server_authentication_methods() -> (Array<BnString>, Array<BnString>) { diff --git a/rust/src/external_library.rs b/rust/src/external_library.rs index 2b3594b6..5360f29d 100644 --- a/rust/src/external_library.rs +++ b/rust/src/external_library.rs @@ -24,10 +24,10 @@ impl ExternalLibrary { } /// Get the name of this external library - pub fn name(&self) -> BnString { + pub fn name(&self) -> String { let result = unsafe { BNExternalLibraryGetName(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Get the file backing this external library diff --git a/rust/src/file_metadata.rs b/rust/src/file_metadata.rs index f1923b40..c14aaf29 100644 --- a/rust/src/file_metadata.rs +++ b/rust/src/file_metadata.rs @@ -68,10 +68,10 @@ impl FileMetadata { unsafe { BNFileMetadataGetSessionId(self.handle) } } - pub fn filename(&self) -> BnString { + pub fn filename(&self) -> String { unsafe { let raw = BNGetFilename(self.handle); - BnString::from_raw(raw) + BnString::into_string(raw) } } @@ -131,8 +131,8 @@ impl FileMetadata { } } - pub fn begin_undo_actions(&self, anonymous_allowed: bool) -> BnString { - unsafe { BnString::from_raw(BNBeginUndoActions(self.handle, anonymous_allowed)) } + pub fn begin_undo_actions(&self, anonymous_allowed: bool) -> String { + unsafe { BnString::into_string(BNBeginUndoActions(self.handle, anonymous_allowed)) } } pub fn commit_undo_actions<S: BnStrCompatible>(&self, id: S) { @@ -161,8 +161,8 @@ impl FileMetadata { } } - pub fn current_view(&self) -> BnString { - unsafe { BnString::from_raw(BNGetCurrentView(self.handle)) } + pub fn current_view(&self) -> String { + unsafe { BnString::into_string(BNGetCurrentView(self.handle)) } } pub fn current_offset(&self) -> u64 { diff --git a/rust/src/function.rs b/rust/src/function.rs index c882ab08..53fec505 100644 --- a/rust/src/function.rs +++ b/rust/src/function.rs @@ -368,8 +368,8 @@ impl Function { } } - pub fn comment(&self) -> BnString { - unsafe { BnString::from_raw(BNGetFunctionComment(self.handle)) } + pub fn comment(&self) -> String { + unsafe { BnString::into_string(BNGetFunctionComment(self.handle)) } } pub fn set_comment<S: BnStrCompatible>(&self, comment: S) { @@ -390,8 +390,8 @@ impl Function { unsafe { BNSetUserFunctionCanReturn(self.handle, &mut bool_with_confidence) } } - pub fn comment_at(&self, addr: u64) -> BnString { - unsafe { BnString::from_raw(BNGetCommentForAddress(self.handle, addr)) } + pub fn comment_at(&self, addr: u64) -> String { + unsafe { BnString::into_string(BNGetCommentForAddress(self.handle, addr)) } } pub fn set_comment_at<S: BnStrCompatible>(&self, addr: u64, comment: S) { @@ -459,11 +459,11 @@ impl Function { unsafe { Array::new(lines, count, ()) } } - pub fn variable_name(&self, var: &Variable) -> BnString { + pub fn variable_name(&self, var: &Variable) -> String { unsafe { let raw_var = BNVariable::from(var); let raw_name = BNGetVariableName(self.handle, &raw_var); - BnString::from_raw(raw_name) + BnString::into_string(raw_name) } } @@ -1741,10 +1741,10 @@ impl Function { value: u64, operand: usize, arch: Option<CoreArchitecture>, - ) -> BnString { + ) -> String { let arch = arch.unwrap_or_else(|| self.arch()); unsafe { - BnString::from_raw(BNGetIntegerConstantDisplayTypeEnumerationType( + BnString::into_string(BNGetIntegerConstantDisplayTypeEnumerationType( self.handle, arch.handle, instr_addr, @@ -1766,7 +1766,7 @@ impl Function { value: u64, operand: usize, arch: Option<CoreArchitecture>, - ) -> (IntegerDisplayType, BnString) { + ) -> (IntegerDisplayType, String) { let arch = arch.unwrap_or_else(|| self.arch()); let name = self.int_enum_display_typeid(instr_addr, value, operand, Some(arch)); let display = self.int_display_type(instr_addr, value, operand, Some(arch)); @@ -1922,7 +1922,7 @@ impl Function { addr: u64, offset: i64, arch: Option<CoreArchitecture>, - ) -> Option<(Variable, BnString, Conf<Ref<Type>>)> { + ) -> Option<NamedVariableWithType> { let arch = arch.unwrap_or_else(|| self.arch()); let mut found_value = BNVariableNameAndType::default(); let found = unsafe { @@ -1937,13 +1937,7 @@ impl Function { if !found { return None; } - let var = Variable::from(found_value.var); - let name = unsafe { BnString::from_raw(found_value.name) }; - let var_type = Conf::new( - unsafe { Type::ref_from_raw(found_value.type_) }, - found_value.typeConfidence, - ); - Some((var, name, var_type)) + Some(NamedVariableWithType::from_owned_raw(found_value)) } pub fn stack_var_at_frame_offset_after_instruction( @@ -1951,7 +1945,7 @@ impl Function { addr: u64, offset: i64, arch: Option<CoreArchitecture>, - ) -> Option<(Variable, BnString, Conf<Ref<Type>>)> { + ) -> Option<NamedVariableWithType> { let arch = arch.unwrap_or_else(|| self.arch()); let mut found_value = BNVariableNameAndType::default(); let found = unsafe { @@ -1966,13 +1960,7 @@ impl Function { if !found { return None; } - let var = Variable::from(found_value.var); - let name = unsafe { BnString::from_raw(found_value.name) }; - let var_type = Conf::new( - unsafe { Type::ref_from_raw(found_value.type_) }, - found_value.typeConfidence, - ); - Some((var, name, var_type)) + Some(NamedVariableWithType::from_owned_raw(found_value)) } pub fn stack_variables_referenced_by( @@ -2348,8 +2336,8 @@ impl Function { /// Returns a string representing the provenance. This portion of the API /// is under development. Currently the provenance information is /// undocumented, not persistent, and not saved to a database. - pub fn provenance(&self) -> BnString { - unsafe { BnString::from_raw(BNGetProvenanceString(self.handle)) } + pub fn provenance(&self) -> String { + unsafe { BnString::into_string(BNGetProvenanceString(self.handle)) } } /// Get registers that are used for the return value @@ -2780,7 +2768,7 @@ impl Default for HighlightColor { #[derive(Clone, Debug, Hash, Eq, PartialEq)] pub struct Comment { pub addr: u64, - pub comment: BnString, + pub comment: String, } impl CoreArrayProvider for Comment { diff --git a/rust/src/headless.rs b/rust/src/headless.rs index 3ea96947..32286331 100644 --- a/rust/src/headless.rs +++ b/rust/src/headless.rs @@ -71,7 +71,7 @@ pub fn init() -> Result<(), InitializationError> { /// /// ⚠️ Important! Must be called at the end of scripts. ⚠️ pub fn shutdown() { - match crate::product().as_str() { + match crate::product().to_string().as_str() { "Binary Ninja Enterprise Client" | "Binary Ninja Ultimate" => { if NEED_LICENSE_RELEASE.load(SeqCst) { enterprise::release_license() diff --git a/rust/src/high_level_il/operation.rs b/rust/src/high_level_il/operation.rs index 340b85a7..c5733a43 100644 --- a/rust/src/high_level_il/operation.rs +++ b/rust/src/high_level_il/operation.rs @@ -16,8 +16,8 @@ pub struct GotoLabel { } impl GotoLabel { - pub fn name(&self) -> BnString { - unsafe { BnString::from_raw(BNGetGotoLabelName(self.function.handle, self.target)) } + pub fn name(&self) -> String { + unsafe { BnString::into_string(BNGetGotoLabelName(self.function.handle, self.target)) } } fn set_name<S: BnStrCompatible>(&self, name: S) { @@ -323,7 +323,7 @@ pub struct LiftedLabel { } impl LiftedLabel { - pub fn name(&self) -> BnString { + pub fn name(&self) -> String { self.target.name() } diff --git a/rust/src/interaction.rs b/rust/src/interaction.rs index 1546bc5a..4a74127b 100644 --- a/rust/src/interaction.rs +++ b/rust/src/interaction.rs @@ -92,8 +92,8 @@ pub fn get_open_filename_input(prompt: &str, extension: &str) -> Option<PathBuf> return None; } - let string = unsafe { BnString::from_raw(value) }; - Some(PathBuf::from(string.as_str())) + let path = unsafe { BnString::into_string(value) }; + Some(PathBuf::from(path)) } pub fn get_save_filename_input( @@ -115,8 +115,8 @@ pub fn get_save_filename_input( return None; } - let string = unsafe { BnString::from_raw(value) }; - Some(PathBuf::from(string.as_str())) + let path = unsafe { BnString::into_string(value) }; + Some(PathBuf::from(path)) } pub fn get_directory_name_input(prompt: &str, default_name: &str) -> Option<PathBuf> { @@ -133,8 +133,8 @@ pub fn get_directory_name_input(prompt: &str, default_name: &str) -> Option<Path return None; } - let string = unsafe { BnString::from_raw(value) }; - Some(PathBuf::from(string.as_str())) + let path = unsafe { BnString::into_string(value) }; + Some(PathBuf::from(path)) } pub type MessageBoxButtonSet = BNMessageBoxButtonSet; diff --git a/rust/src/lib.rs b/rust/src/lib.rs index a3df0cd3..0446fe60 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -433,8 +433,8 @@ pub trait ObjectDestructor: 'static + Sync + Sized { } } -pub fn version() -> BnString { - unsafe { BnString::from_raw(BNGetVersionString()) } +pub fn version() -> String { + unsafe { BnString::into_string(BNGetVersionString()) } } pub fn build_id() -> u32 { @@ -512,16 +512,16 @@ pub fn version_info() -> VersionInfo { VersionInfo::from_owned_raw(info_raw) } -pub fn serial_number() -> BnString { - unsafe { BnString::from_raw(BNGetSerialNumber()) } +pub fn serial_number() -> String { + unsafe { BnString::into_string(BNGetSerialNumber()) } } pub fn is_license_validated() -> bool { unsafe { BNIsLicenseValidated() } } -pub fn licensed_user_email() -> BnString { - unsafe { BnString::from_raw(BNGetLicensedUserEmail()) } +pub fn licensed_user_email() -> String { + unsafe { BnString::into_string(BNGetLicensedUserEmail()) } } pub fn license_path() -> PathBuf { @@ -547,12 +547,12 @@ pub fn set_license<S: BnStrCompatible + Default>(license: Option<S>) { #[cfg(feature = "demo")] pub fn set_license<S: BnStrCompatible + Default>(_license: Option<S>) {} -pub fn product() -> BnString { - unsafe { BnString::from_raw(BNGetProduct()) } +pub fn product() -> String { + unsafe { BnString::into_string(BNGetProduct()) } } -pub fn product_type() -> BnString { - unsafe { BnString::from_raw(BNGetProductType()) } +pub fn product_type() -> String { + unsafe { BnString::into_string(BNGetProductType()) } } pub fn license_expiration_time() -> std::time::SystemTime { diff --git a/rust/src/logger.rs b/rust/src/logger.rs index c928287f..c06f4dfc 100644 --- a/rust/src/logger.rs +++ b/rust/src/logger.rs @@ -66,8 +66,8 @@ impl Logger { } } - pub fn name(&self) -> BnString { - unsafe { BnString::from_raw(BNLoggerGetName(self.handle.as_ptr())) } + pub fn name(&self) -> String { + unsafe { BnString::into_string(BNLoggerGetName(self.handle.as_ptr())) } } pub fn session_id(&self) -> usize { @@ -144,7 +144,7 @@ impl log::Log for Ref<Logger> { BNLog( self.session_id(), level, - logger_name.as_ptr(), + logger_name.as_ptr() as *const c_char, 0, percent_s.as_ptr(), msg.as_ptr(), diff --git a/rust/src/platform.rs b/rust/src/platform.rs index 72f61430..6d2b30f0 100644 --- a/rust/src/platform.rs +++ b/rust/src/platform.rs @@ -160,10 +160,10 @@ impl Platform { } } - pub fn name(&self) -> BnString { + pub fn name(&self) -> String { unsafe { let raw_name = BNGetPlatformName(self.handle); - BnString::from_raw(raw_name) + BnString::into_string(raw_name) } } @@ -301,7 +301,7 @@ impl Platform { assert!(!error_string.is_null()); Err(TypeParserError::new( TypeParserErrorSeverity::FatalSeverity, - unsafe { BnString::from_raw(error_string) }.to_string(), + unsafe { BnString::into_string(error_string) }, file_name.to_string(), 0, 0, diff --git a/rust/src/project.rs b/rust/src/project.rs index fad1e5ef..ebb6949e 100644 --- a/rust/src/project.rs +++ b/rust/src/project.rs @@ -84,18 +84,18 @@ impl Project { } /// Get the unique id of this project - pub fn id(&self) -> BnString { - unsafe { BnString::from_raw(BNProjectGetId(self.handle.as_ptr())) } + pub fn id(&self) -> String { + unsafe { BnString::into_string(BNProjectGetId(self.handle.as_ptr())) } } /// Get the path of the project - pub fn path(&self) -> BnString { - unsafe { BnString::from_raw(BNProjectGetPath(self.handle.as_ptr())) } + pub fn path(&self) -> String { + unsafe { BnString::into_string(BNProjectGetPath(self.handle.as_ptr())) } } /// Get the name of the project - pub fn name(&self) -> BnString { - unsafe { BnString::from_raw(BNProjectGetName(self.handle.as_ptr())) } + pub fn name(&self) -> String { + unsafe { BnString::into_string(BNProjectGetName(self.handle.as_ptr())) } } /// Set the name of the project @@ -110,8 +110,8 @@ impl Project { } /// Get the description of the project - pub fn description(&self) -> BnString { - unsafe { BnString::from_raw(BNProjectGetDescription(self.handle.as_ptr())) } + pub fn description(&self) -> String { + unsafe { BnString::into_string(BNProjectGetDescription(self.handle.as_ptr())) } } /// Set the description of the project diff --git a/rust/src/project/file.rs b/rust/src/project/file.rs index 5071dd50..35f25937 100644 --- a/rust/src/project/file.rs +++ b/rust/src/project/file.rs @@ -37,8 +37,8 @@ impl ProjectFile { } /// Get the path on disk to this file's contents - pub fn path_on_disk(&self) -> BnString { - unsafe { BnString::from_raw(BNProjectFileGetPathOnDisk(self.handle.as_ptr())) } + pub fn path_on_disk(&self) -> String { + unsafe { BnString::into_string(BNProjectFileGetPathOnDisk(self.handle.as_ptr())) } } /// Check if this file's contents exist on disk @@ -47,13 +47,13 @@ impl ProjectFile { } /// Get the unique id of this file - pub fn id(&self) -> BnString { - unsafe { BnString::from_raw(BNProjectFileGetId(self.handle.as_ptr())) } + pub fn id(&self) -> String { + unsafe { BnString::into_string(BNProjectFileGetId(self.handle.as_ptr())) } } /// Get the name of this file - pub fn name(&self) -> BnString { - unsafe { BnString::from_raw(BNProjectFileGetName(self.handle.as_ptr())) } + pub fn name(&self) -> String { + unsafe { BnString::into_string(BNProjectFileGetName(self.handle.as_ptr())) } } /// Set the name of this file @@ -68,8 +68,8 @@ impl ProjectFile { } /// Get the description of this file - pub fn description(&self) -> BnString { - unsafe { BnString::from_raw(BNProjectFileGetDescription(self.handle.as_ptr())) } + pub fn description(&self) -> String { + unsafe { BnString::into_string(BNProjectFileGetDescription(self.handle.as_ptr())) } } /// Set the description of this file diff --git a/rust/src/project/folder.rs b/rust/src/project/folder.rs index 90b40051..316abeaf 100644 --- a/rust/src/project/folder.rs +++ b/rust/src/project/folder.rs @@ -36,13 +36,13 @@ impl ProjectFolder { } /// Get the unique id of this folder - pub fn id(&self) -> BnString { - unsafe { BnString::from_raw(BNProjectFolderGetId(self.handle.as_ptr())) } + pub fn id(&self) -> String { + unsafe { BnString::into_string(BNProjectFolderGetId(self.handle.as_ptr())) } } /// Get the name of this folder - pub fn name(&self) -> BnString { - unsafe { BnString::from_raw(BNProjectFolderGetName(self.handle.as_ptr())) } + pub fn name(&self) -> String { + unsafe { BnString::into_string(BNProjectFolderGetName(self.handle.as_ptr())) } } /// Set the name of this folder @@ -57,8 +57,8 @@ impl ProjectFolder { } /// Get the description of this folder - pub fn description(&self) -> BnString { - unsafe { BnString::from_raw(BNProjectFolderGetDescription(self.handle.as_ptr())) } + pub fn description(&self) -> String { + unsafe { BnString::into_string(BNProjectFolderGetDescription(self.handle.as_ptr())) } } /// Set the description of this folder diff --git a/rust/src/repository.rs b/rust/src/repository.rs index 135b2367..90e414d5 100644 --- a/rust/src/repository.rs +++ b/rust/src/repository.rs @@ -31,17 +31,17 @@ impl Repository { } /// String URL of the git repository where the plugin repository's are stored - pub fn url(&self) -> BnString { + pub fn url(&self) -> String { let result = unsafe { BNRepositoryGetUrl(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result as *mut c_char) } + unsafe { BnString::into_string(result as *mut c_char) } } /// String local path to store the given plugin repository - pub fn path(&self) -> BnString { + pub fn path(&self) -> String { let result = unsafe { BNRepositoryGetRepoPath(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result as *mut c_char) } + unsafe { BnString::into_string(result as *mut c_char) } } /// List of RepoPlugin objects contained within this repository @@ -65,10 +65,10 @@ impl Repository { // TODO: Make this a PathBuf? /// String full path the repository - pub fn full_path(&self) -> BnString { + pub fn full_path(&self) -> String { let result = unsafe { BNRepositoryGetPluginsPath(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result as *mut c_char) } + unsafe { BnString::into_string(result as *mut c_char) } } } diff --git a/rust/src/repository/plugin.rs b/rust/src/repository/plugin.rs index af3886f2..82309e79 100644 --- a/rust/src/repository/plugin.rs +++ b/rust/src/repository/plugin.rs @@ -31,31 +31,31 @@ impl RepositoryPlugin { } /// String of the plugin author - pub fn author(&self) -> BnString { + pub fn author(&self) -> String { let result = unsafe { BNPluginGetAuthor(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result as *mut c_char) } + unsafe { BnString::into_string(result as *mut c_char) } } /// String short description of the plugin - pub fn description(&self) -> BnString { + pub fn description(&self) -> String { let result = unsafe { BNPluginGetDescription(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result as *mut c_char) } + unsafe { BnString::into_string(result as *mut c_char) } } /// String complete license text for the given plugin - pub fn license_text(&self) -> BnString { + pub fn license_text(&self) -> String { let result = unsafe { BNPluginGetLicenseText(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result as *mut c_char) } + unsafe { BnString::into_string(result as *mut c_char) } } /// String long description of the plugin - pub fn long_description(&self) -> BnString { + pub fn long_description(&self) -> String { let result = unsafe { BNPluginGetLongdescription(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result as *mut c_char) } + unsafe { BnString::into_string(result as *mut c_char) } } /// Minimum version info the plugin was tested on @@ -71,65 +71,65 @@ impl RepositoryPlugin { } /// String plugin name - pub fn name(&self) -> BnString { + pub fn name(&self) -> String { let result = unsafe { BNPluginGetName(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result as *mut c_char) } + unsafe { BnString::into_string(result as *mut c_char) } } /// String URL of the plugin's git repository - pub fn project_url(&self) -> BnString { + pub fn project_url(&self) -> String { let result = unsafe { BNPluginGetProjectUrl(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result as *mut c_char) } + unsafe { BnString::into_string(result as *mut c_char) } } /// String URL of the plugin's git repository - pub fn package_url(&self) -> BnString { + pub fn package_url(&self) -> String { let result = unsafe { BNPluginGetPackageUrl(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result as *mut c_char) } + unsafe { BnString::into_string(result as *mut c_char) } } /// String URL of the plugin author's url - pub fn author_url(&self) -> BnString { + pub fn author_url(&self) -> String { let result = unsafe { BNPluginGetAuthorUrl(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result as *mut c_char) } + unsafe { BnString::into_string(result as *mut c_char) } } /// String version of the plugin - pub fn version(&self) -> BnString { + pub fn version(&self) -> String { let result = unsafe { BNPluginGetVersion(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result as *mut c_char) } + unsafe { BnString::into_string(result as *mut c_char) } } /// String of the commit of this plugin git repository - pub fn commit(&self) -> BnString { + pub fn commit(&self) -> String { let result = unsafe { BNPluginGetCommit(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result as *mut c_char) } + unsafe { BnString::into_string(result as *mut c_char) } } /// Relative path from the base of the repository to the actual plugin - pub fn path(&self) -> BnString { + pub fn path(&self) -> String { let result = unsafe { BNPluginGetPath(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result as *mut c_char) } + unsafe { BnString::into_string(result as *mut c_char) } } /// Optional sub-directory the plugin code lives in as a relative path from the plugin root - pub fn subdir(&self) -> BnString { + pub fn subdir(&self) -> String { let result = unsafe { BNPluginGetSubdir(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result as *mut c_char) } + unsafe { BnString::into_string(result as *mut c_char) } } /// Dependencies required for installing this plugin - pub fn dependencies(&self) -> BnString { + pub fn dependencies(&self) -> String { let result = unsafe { BNPluginGetDependencies(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result as *mut c_char) } + unsafe { BnString::into_string(result as *mut c_char) } } /// true if the plugin is installed, false otherwise @@ -190,10 +190,10 @@ impl RepositoryPlugin { unsafe { Array::new(result, count, ()) } } - pub fn repository(&self) -> BnString { + pub fn repository(&self) -> String { let result = unsafe { BNPluginGetRepository(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result as *mut c_char) } + unsafe { BnString::into_string(result as *mut c_char) } } /// Boolean status indicating that the plugin is being deleted @@ -237,10 +237,10 @@ impl RepositoryPlugin { } /// Gets a json object of the project data field - pub fn project_data(&self) -> BnString { + pub fn project_data(&self) -> String { let result = unsafe { BNPluginGetProjectData(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Returns a datetime object representing the plugins last update diff --git a/rust/src/secrets_provider.rs b/rust/src/secrets_provider.rs index e61cd466..5f42dbea 100644 --- a/rust/src/secrets_provider.rs +++ b/rust/src/secrets_provider.rs @@ -56,10 +56,10 @@ impl CoreSecretsProvider { NonNull::new(result).map(|h| unsafe { Self::from_raw(h) }) } - pub fn name(&self) -> BnString { + pub fn name(&self) -> String { let result = unsafe { BNGetSecretsProviderName(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Check if data for a specific key exists, but do not retrieve it @@ -71,12 +71,12 @@ impl CoreSecretsProvider { } /// Retrieve data for the given key, if it exists - pub fn get_data<S: BnStrCompatible>(&self, key: S) -> BnString { + pub fn get_data<S: BnStrCompatible>(&self, key: S) -> String { let key = key.into_bytes_with_nul(); let result = unsafe { BNGetSecretsProviderData(self.handle.as_ptr(), key.as_ref().as_ptr() as *const c_char) }; - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Store data with the given key diff --git a/rust/src/section.rs b/rust/src/section.rs index c88ef9b0..46a201d4 100644 --- a/rust/src/section.rs +++ b/rust/src/section.rs @@ -90,12 +90,12 @@ impl Section { SectionBuilder::new(name, range) } - pub fn name(&self) -> BnString { - unsafe { BnString::from_raw(BNSectionGetName(self.handle)) } + pub fn name(&self) -> String { + unsafe { BnString::into_string(BNSectionGetName(self.handle)) } } - pub fn section_type(&self) -> BnString { - unsafe { BnString::from_raw(BNSectionGetType(self.handle)) } + pub fn section_type(&self) -> String { + unsafe { BnString::into_string(BNSectionGetType(self.handle)) } } pub fn start(&self) -> u64 { @@ -122,12 +122,12 @@ impl Section { unsafe { BNSectionGetSemantics(self.handle).into() } } - pub fn linked_section(&self) -> BnString { - unsafe { BnString::from_raw(BNSectionGetLinkedSection(self.handle)) } + pub fn linked_section(&self) -> String { + unsafe { BnString::into_string(BNSectionGetLinkedSection(self.handle)) } } - pub fn info_section(&self) -> BnString { - unsafe { BnString::from_raw(BNSectionGetInfoSection(self.handle)) } + pub fn info_section(&self) -> String { + unsafe { BnString::into_string(BNSectionGetInfoSection(self.handle)) } } pub fn info_data(&self) -> u64 { diff --git a/rust/src/settings.rs b/rust/src/settings.rs index 8c64f314..4b4d418f 100644 --- a/rust/src/settings.rs +++ b/rust/src/settings.rs @@ -58,8 +58,8 @@ impl Settings { unsafe { BNSettingsSetResourceId(self.handle, resource_id.as_ref().as_ptr() as *mut _) }; } - pub fn serialize_schema(&self) -> BnString { - unsafe { BnString::from_raw(BNSettingsSerializeSchema(self.handle)) } + pub fn serialize_schema(&self) -> String { + unsafe { BnString::into_string(BNSettingsSerializeSchema(self.handle)) } } pub fn deserialize_schema<S: BnStrCompatible>(&self, schema: S) -> bool { @@ -184,7 +184,7 @@ impl Settings { } } - pub fn get_string<S: BnStrCompatible>(&self, key: S) -> BnString { + pub fn get_string<S: BnStrCompatible>(&self, key: S) -> String { self.get_string_with_opts(key, &mut QueryOptions::default()) } @@ -192,7 +192,7 @@ impl Settings { &self, key: S, options: &mut QueryOptions, - ) -> BnString { + ) -> String { let key = key.into_bytes_with_nul(); let view_ptr = match options.view.as_ref() { Some(view) => view.handle, @@ -203,7 +203,7 @@ impl Settings { _ => std::ptr::null_mut(), }; unsafe { - BnString::from_raw(BNSettingsGetString( + BnString::into_string(BNSettingsGetString( self.handle, key.as_ref().as_ptr() as *mut _, view_ptr, @@ -248,7 +248,7 @@ impl Settings { } } - pub fn get_json<S: BnStrCompatible>(&self, key: S) -> BnString { + pub fn get_json<S: BnStrCompatible>(&self, key: S) -> String { self.get_json_with_opts(key, &mut QueryOptions::default()) } @@ -256,7 +256,7 @@ impl Settings { &self, key: S, options: &mut QueryOptions, - ) -> BnString { + ) -> String { let key = key.into_bytes_with_nul(); let view_ptr = match options.view.as_ref() { Some(view) => view.handle, @@ -267,7 +267,7 @@ impl Settings { _ => std::ptr::null_mut(), }; unsafe { - BnString::from_raw(BNSettingsGetJson( + BnString::into_string(BNSettingsGetJson( self.handle, key.as_ref().as_ptr() as *mut _, view_ptr, @@ -479,11 +479,11 @@ impl Settings { } } - pub fn get_property_string<S: BnStrCompatible>(&self, key: S, property: S) -> BnString { + pub fn get_property_string<S: BnStrCompatible>(&self, key: S, property: S) -> String { let key = key.into_bytes_with_nul(); let property = property.into_bytes_with_nul(); unsafe { - BnString::from_raw(BNSettingsQueryPropertyString( + BnString::into_string(BNSettingsQueryPropertyString( self.handle, key.as_ref().as_ptr() as *mut _, property.as_ref().as_ptr() as *mut _, diff --git a/rust/src/string.rs b/rust/src/string.rs index f9224851..3cdbf384 100644 --- a/rust/src/string.rs +++ b/rust/src/string.rs @@ -69,10 +69,25 @@ impl BnString { } } + /// Take an owned core string and convert it to [`String`]. + /// + /// This expects the passed raw string to be owned, as in, freed by us. + pub unsafe fn into_string(raw: *mut c_char) -> String { + Self::from_raw(raw).to_string() + } + /// Construct a BnString from an owned const char* allocated by BNAllocString pub(crate) unsafe fn from_raw(raw: *mut c_char) -> Self { Self { raw } } + + /// Free a raw string allocated by BNAllocString. + pub(crate) unsafe fn free_raw(raw: *mut c_char) { + use binaryninjacore_sys::BNFreeString; + if !raw.is_null() { + BNFreeString(raw); + } + } /// Consumes the `BnString`, returning a raw pointer to the string. /// @@ -87,34 +102,11 @@ impl BnString { mem::forget(value); res } - - pub fn as_str(&self) -> &str { - unsafe { CStr::from_ptr(self.raw).to_str().unwrap() } - } - - pub fn as_bytes(&self) -> &[u8] { - self.as_str().as_bytes() - } - - pub fn as_bytes_with_null(&self) -> &[u8] { - self.deref().to_bytes() - } - - pub fn len(&self) -> usize { - self.as_str().len() - } - - pub fn is_empty(&self) -> bool { - self.as_str().is_empty() - } } impl Drop for BnString { fn drop(&mut self) { - use binaryninjacore_sys::BNFreeString; - unsafe { - BNFreeString(self.raw); - } + unsafe { BnString::free_raw(self.raw) }; } } @@ -137,6 +129,18 @@ impl Deref for BnString { } } +impl From<String> for BnString { + fn from(s: String) -> Self { + Self::new(s) + } +} + +impl From<&str> for BnString { + fn from(s: &str) -> Self { + Self::new(s) + } +} + impl AsRef<[u8]> for BnString { fn as_ref(&self) -> &[u8] { self.to_bytes_with_nul() @@ -208,6 +212,14 @@ unsafe impl BnStrCompatible for BnString { } } +unsafe impl BnStrCompatible for &BnString { + type Result = Self; + + fn into_bytes_with_nul(self) -> Self::Result { + self + } +} + unsafe impl BnStrCompatible for CString { type Result = Vec<u8>; diff --git a/rust/src/tags.rs b/rust/src/tags.rs index 2db3a58c..63c3634a 100644 --- a/rust/src/tags.rs +++ b/rust/src/tags.rs @@ -47,12 +47,12 @@ impl Tag { unsafe { Self::ref_from_raw(BNCreateTag(t.handle, data.as_ref().as_ptr() as *mut _)) } } - pub fn id(&self) -> BnString { - unsafe { BnString::from_raw(BNTagGetId(self.handle)) } + pub fn id(&self) -> String { + unsafe { BnString::into_string(BNTagGetId(self.handle)) } } - pub fn data(&self) -> BnString { - unsafe { BnString::from_raw(BNTagGetData(self.handle)) } + pub fn data(&self) -> String { + unsafe { BnString::into_string(BNTagGetData(self.handle)) } } pub fn ty(&self) -> Ref<TagType> { @@ -145,12 +145,12 @@ impl TagType { tag_type } - pub fn id(&self) -> BnString { - unsafe { BnString::from_raw(BNTagTypeGetId(self.handle)) } + pub fn id(&self) -> String { + unsafe { BnString::into_string(BNTagTypeGetId(self.handle)) } } - pub fn icon(&self) -> BnString { - unsafe { BnString::from_raw(BNTagTypeGetIcon(self.handle)) } + pub fn icon(&self) -> String { + unsafe { BnString::into_string(BNTagTypeGetIcon(self.handle)) } } pub fn set_icon<S: BnStrCompatible>(&self, icon: S) { @@ -160,8 +160,8 @@ impl TagType { } } - pub fn name(&self) -> BnString { - unsafe { BnString::from_raw(BNTagTypeGetName(self.handle)) } + pub fn name(&self) -> String { + unsafe { BnString::into_string(BNTagTypeGetName(self.handle)) } } pub fn set_name<S: BnStrCompatible>(&self, name: S) { diff --git a/rust/src/type_archive.rs b/rust/src/type_archive.rs index f10cda50..2c8caa39 100644 --- a/rust/src/type_archive.rs +++ b/rust/src/type_archive.rs @@ -757,8 +757,8 @@ impl TypeArchive { ) }; assert!(!result.is_null()); - let id_str = unsafe { BnString::from_raw(result) }; - TypeArchiveSnapshotId(id_str.to_string()) + let id_str = unsafe { BnString::into_string(result) }; + TypeArchiveSnapshotId(id_str) } /// Merge two snapshots in the archive to produce a new snapshot @@ -1140,10 +1140,10 @@ impl TypeArchiveMergeConflict { NonNull::new(value).map(|handle| unsafe { TypeArchive::ref_from_raw(handle) }) } - pub fn type_id(&self) -> BnString { + pub fn type_id(&self) -> String { let value = unsafe { BNTypeArchiveMergeConflictGetTypeId(self.handle.as_ptr()) }; assert!(!value.is_null()); - unsafe { BnString::from_raw(value) } + unsafe { BnString::into_string(value) } } pub fn base_snapshot_id(&self) -> TypeArchiveSnapshotId { diff --git a/rust/src/type_container.rs b/rust/src/type_container.rs index 947c6912..1535732d 100644 --- a/rust/src/type_container.rs +++ b/rust/src/type_container.rs @@ -44,17 +44,17 @@ impl TypeContainer { /// Get an id string for the Type Container. This will be unique within a given /// analysis session, but may not be globally unique. - pub fn id(&self) -> BnString { + pub fn id(&self) -> String { let result = unsafe { BNTypeContainerGetId(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Get a user-friendly name for the Type Container. - pub fn name(&self) -> BnString { + pub fn name(&self) -> String { let result = unsafe { BNTypeContainerGetName(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Get the type of underlying model the Type Container is accessing. diff --git a/rust/src/type_parser.rs b/rust/src/type_parser.rs index 656f0c9d..22c4ba76 100644 --- a/rust/src/type_parser.rs +++ b/rust/src/type_parser.rs @@ -61,10 +61,10 @@ impl CoreTypeParser { NonNull::new(result).map(|x| unsafe { Self::from_raw(x) }) } - pub fn name(&self) -> BnString { + pub fn name(&self) -> String { let result = unsafe { BNGetTypeParserName(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } } diff --git a/rust/src/type_printer.rs b/rust/src/type_printer.rs index 12c71645..124079ec 100644 --- a/rust/src/type_printer.rs +++ b/rust/src/type_printer.rs @@ -67,10 +67,10 @@ impl CoreTypePrinter { NonNull::new(result).map(|x| unsafe { Self::from_raw(x) }) } - pub fn name(&self) -> BnString { + pub fn name(&self) -> String { let result = unsafe { BNGetTypePrinterName(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } pub fn get_type_tokens<T: Into<QualifiedName>>( diff --git a/rust/src/types.rs b/rust/src/types.rs index 9d1353bd..8dbeeb48 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -932,9 +932,9 @@ impl Type { } } - pub fn generate_auto_demangled_type_id<T: Into<QualifiedName>>(name: T) -> BnString { + pub fn generate_auto_demangled_type_id<T: Into<QualifiedName>>(name: T) -> String { let mut raw_name = QualifiedName::into_raw(name.into()); - let type_id = unsafe { BnString::from_raw(BNGenerateAutoDemangledTypeId(&mut raw_name)) }; + let type_id = unsafe { BnString::into_string(BNGenerateAutoDemangledTypeId(&mut raw_name)) }; QualifiedName::free_raw(raw_name); type_id } @@ -2334,7 +2334,7 @@ impl NameAndType { } pub(crate) fn free_raw(value: BNNameAndType) { - let _ = unsafe { BnString::from_raw(value.name) }; + unsafe { BnString::free_raw(value.name) }; let _ = unsafe { Type::ref_from_raw(value.type_) }; } diff --git a/rust/src/update.rs b/rust/src/update.rs index 2a22c9c9..9afb1218 100644 --- a/rust/src/update.rs +++ b/rust/src/update.rs @@ -242,8 +242,8 @@ impl UpdateVersion { } pub(crate) fn free_raw(value: BNUpdateVersion) { - let _ = unsafe { BnString::from_raw(value.version) }; - let _ = unsafe { BnString::from_raw(value.notes) }; + unsafe { BnString::free_raw(value.version) }; + unsafe { BnString::free_raw(value.notes) }; } } diff --git a/rust/src/websocket/provider.rs b/rust/src/websocket/provider.rs index 0e28afe4..2d01fbc3 100644 --- a/rust/src/websocket/provider.rs +++ b/rust/src/websocket/provider.rs @@ -87,10 +87,10 @@ impl CoreWebsocketProvider { NonNull::new(result).map(|h| unsafe { Self::from_raw(h) }) } - pub fn name(&self) -> BnString { + pub fn name(&self) -> String { let result = unsafe { BNGetWebsocketProviderName(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } } diff --git a/rust/src/workflow.rs b/rust/src/workflow.rs index ca42ff68..71a60824 100644 --- a/rust/src/workflow.rs +++ b/rust/src/workflow.rs @@ -204,10 +204,10 @@ impl Activity { unsafe { Activity::ref_from_raw(NonNull::new(result).unwrap()) } } - pub fn name(&self) -> BnString { + pub fn name(&self) -> String { let result = unsafe { BNActivityGetName(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } } @@ -303,10 +303,10 @@ impl Workflow { unsafe { Array::new(result, count, ()) } } - pub fn name(&self) -> BnString { + pub fn name(&self) -> String { let result = unsafe { BNGetWorkflowName(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Register this [Workflow], making it immutable and available for use. @@ -382,7 +382,7 @@ impl Workflow { } /// Retrieve the configuration as an adjacency list in JSON for the [Workflow]. - pub fn configuration(&self) -> BnString { + pub fn configuration(&self) -> String { self.configuration_with_activity("") } @@ -390,7 +390,7 @@ impl Workflow { /// [Workflow], just for the given `activity`. /// /// `activity` - return the configuration for the `activity` - pub fn configuration_with_activity<A: BnStrCompatible>(&self, activity: A) -> BnString { + pub fn configuration_with_activity<A: BnStrCompatible>(&self, activity: A) -> String { let result = unsafe { BNWorkflowGetConfiguration( self.handle.as_ptr(), @@ -398,7 +398,7 @@ impl Workflow { ) }; assert!(!result.is_null()); - unsafe { BnString::from_raw(result) } + unsafe { BnString::into_string(result) } } /// Whether this [Workflow] is registered or not. A [Workflow] becomes immutable once registered. |
