From f741ac93d5bc76844a81f5ddaa3b71df1863189e Mon Sep 17 00:00:00 2001 From: Mason Reed Date: Fri, 17 Jan 2025 21:32:47 -0500 Subject: [PATCH] More rust cleanup - Fixed progress executor freeing itself after one iteration - Updated the last of the doc imports - Moved mainthread to main_thread - Made project creation and opening failable We could probably AsRef to get around the allocation and free inside the function bodies, not high priority as those functions are long running anyways. --- rust/README.md | 2 +- rust/src/binary_view.rs | 12 ++++-- rust/src/database.rs | 7 +++- rust/src/database/snapshot.rs | 22 ++++++++--- rust/src/debuginfo.rs | 7 +++- rust/src/file_metadata.rs | 17 +++++--- rust/src/headless.rs | 2 +- rust/src/lib.rs | 21 ++++++---- rust/src/{mainthread.rs => main_thread.rs} | 0 rust/src/medium_level_il/function.rs | 4 +- rust/src/progress.rs | 9 +---- rust/src/project.rs | 45 +++++++++++++++------- rust/src/project/file.rs | 4 +- rust/src/project/folder.rs | 16 +++++--- rust/src/type_archive.rs | 6 ++- rust/src/type_container.rs | 7 +++- rust/src/update.rs | 12 ++++-- rust/tests/mainthread.rs | 2 +- rust/tests/project.rs | 18 ++++----- 19 files changed, 138 insertions(+), 75 deletions(-) rename rust/src/{mainthread.rs => main_thread.rs} (100%) diff --git a/rust/README.md b/rust/README.md index 727a820c5..0d627f6f2 100644 --- a/rust/README.md +++ b/rust/README.md @@ -18,7 +18,7 @@ To specify a specific commit see the cargo documentation [here](https://doc.rust ```rust use binaryninja::headless::Session; -use binaryninja::binaryview::{BinaryViewBase, BinaryViewExt}; +use binaryninja::binary_view::{BinaryViewBase, BinaryViewExt}; fn main() { let headless_session = Session::new().expect("Failed to initialize session"); diff --git a/rust/src/binary_view.rs b/rust/src/binary_view.rs index 824803145..691f42c86 100644 --- a/rust/src/binary_view.rs +++ b/rust/src/binary_view.rs @@ -56,7 +56,7 @@ use crate::types::{ use crate::variable::DataVariable; use crate::Endianness; use std::collections::HashMap; -use std::ffi::c_char; +use std::ffi::{c_char, c_void}; use std::ops::Range; use std::path::Path; use std::ptr::NonNull; @@ -645,17 +645,20 @@ pub trait BinaryViewExt: BinaryViewBase { .collect(); let mut result_ids: *mut *mut c_char = std::ptr::null_mut(); let mut result_names: *mut BNQualifiedName = std::ptr::null_mut(); + let boxed_progress = Box::new(progress.into()); + let leaked_boxed_progress = Box::into_raw(boxed_progress); let result_count = unsafe { BNDefineAnalysisTypes( self.as_ref().handle, types.as_mut_ptr(), types.len(), Some(ProgressExecutor::cb_execute), - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, &mut result_ids as *mut _, &mut result_names as *mut _, ) }; + let _ = unsafe { Box::from_raw(leaked_boxed_progress) }; for ty in types { QualifiedNameTypeAndId::free_raw(ty); @@ -690,15 +693,18 @@ pub trait BinaryViewExt: BinaryViewBase { .map(Into::into) .map(QualifiedNameAndType::into_raw) .collect(); + let boxed_progress = Box::new(progress.into()); + let leaked_boxed_progress = Box::into_raw(boxed_progress); unsafe { BNDefineUserAnalysisTypes( self.as_ref().handle, types.as_mut_ptr(), types.len(), Some(ProgressExecutor::cb_execute), - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, ) }; + let _ = unsafe { Box::from_raw(leaked_boxed_progress) }; for ty in types { QualifiedNameAndType::free_raw(ty); } diff --git a/rust/src/database.rs b/rust/src/database.rs index 77a5a2288..6a43a963b 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; +use std::ffi::{c_char, c_void}; use std::fmt::Debug; use std::ptr::NonNull; @@ -94,6 +94,8 @@ impl Database { { let name_raw = name.into_bytes_with_nul(); let name_ptr = name_raw.as_ref().as_ptr() as *const c_char; + let boxed_progress = Box::new(progress.into()); + let leaked_boxed_progress = Box::into_raw(boxed_progress); let new_id = unsafe { BNWriteDatabaseSnapshotData( self.handle.as_ptr(), @@ -104,10 +106,11 @@ impl Database { name_ptr, data.handle.as_ptr(), auto_save, - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, Some(ProgressExecutor::cb_execute), ) }; + let _ = unsafe { Box::from_raw(leaked_boxed_progress) }; SnapshotId(new_id) } diff --git a/rust/src/database/snapshot.rs b/rust/src/database/snapshot.rs index fd678c4f1..bceceb7eb 100644 --- a/rust/src/database/snapshot.rs +++ b/rust/src/database/snapshot.rs @@ -14,7 +14,7 @@ use binaryninjacore_sys::{ BNSnapshot, BNSnapshotHasAncestor, BNSnapshotHasContents, BNSnapshotHasUndo, BNSnapshotStoreData, }; -use std::ffi::c_char; +use std::ffi::{c_char, c_void}; use std::fmt; use std::fmt::{Debug, Display, Formatter}; use std::ptr::NonNull; @@ -136,14 +136,17 @@ impl Snapshot { ) -> Array { assert!(self.has_undo()); let mut count = 0; + let boxed_progress = Box::new(progress.into()); + let leaked_boxed_progress = Box::into_raw(boxed_progress); let result = unsafe { BNGetSnapshotUndoEntriesWithProgress( self.handle.as_ptr(), - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, Some(ProgressExecutor::cb_execute), &mut count, ) }; + let _ = unsafe { Box::from_raw(leaked_boxed_progress) }; assert!(!result.is_null()); unsafe { Array::new(result, count, ()) } } @@ -158,13 +161,16 @@ impl Snapshot { &self, progress: impl Into, ) -> Ref { + let boxed_progress = Box::new(progress.into()); + let leaked_boxed_progress = Box::into_raw(boxed_progress); let result = unsafe { BNReadSnapshotDataWithProgress( self.handle.as_ptr(), - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, Some(ProgressExecutor::cb_execute), ) }; + let _ = unsafe { Box::from_raw(leaked_boxed_progress) }; unsafe { KeyValueStore::ref_from_raw(NonNull::new(result).unwrap()) } } @@ -190,14 +196,18 @@ impl Snapshot { data: &KeyValueStore, progress: impl Into, ) -> bool { - unsafe { + let boxed_progress = Box::new(progress.into()); + let leaked_boxed_progress = Box::into_raw(boxed_progress); + let success = unsafe { BNSnapshotStoreData( self.handle.as_ptr(), data.handle.as_ptr(), - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, Some(ProgressExecutor::cb_execute), ) - } + }; + let _ = unsafe { Box::from_raw(leaked_boxed_progress) }; + success } /// Determine if this snapshot has another as an ancestor diff --git a/rust/src/debuginfo.rs b/rust/src/debuginfo.rs index 42fa598e7..ece965b03 100644 --- a/rust/src/debuginfo.rs +++ b/rust/src/debuginfo.rs @@ -177,6 +177,8 @@ impl DebugInfoParser { existing_debug_info: Option<&DebugInfo>, progress: impl Into, ) -> Option> { + let boxed_progress = Box::new(progress.into()); + let leaked_boxed_progress = Box::into_raw(boxed_progress); let info: *mut BNDebugInfo = match existing_debug_info { Some(debug_info) => unsafe { BNParseDebugInfo( @@ -185,7 +187,7 @@ impl DebugInfoParser { debug_file.handle, debug_info.handle, Some(ProgressExecutor::cb_execute), - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, ) }, None => unsafe { @@ -195,10 +197,11 @@ impl DebugInfoParser { debug_file.handle, std::ptr::null_mut(), Some(ProgressExecutor::cb_execute), - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, ) }, }; + let _ = unsafe { Box::from_raw(leaked_boxed_progress) }; if info.is_null() { return None; } diff --git a/rust/src/file_metadata.rs b/rust/src/file_metadata.rs index 8be2c402f..8776cfba2 100644 --- a/rust/src/file_metadata.rs +++ b/rust/src/file_metadata.rs @@ -24,6 +24,7 @@ use binaryninjacore_sys::{ BNSaveAutoSnapshot, BNSetFilename, BNUndo, }; use binaryninjacore_sys::{BNCreateDatabaseWithProgress, BNOpenExistingDatabaseWithProgress}; +use std::ffi::c_void; use std::fmt::Debug; use crate::rc::*; @@ -226,15 +227,19 @@ impl FileMetadata { return false; }; - unsafe { + let boxed_progress = Box::new(progress.into()); + let leaked_boxed_progress = Box::into_raw(boxed_progress); + let success = unsafe { BNCreateDatabaseWithProgress( raw_view.handle, filename_ptr, - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, Some(ProgressExecutor::cb_execute), ptr::null_mut(), ) - } + }; + let _ = unsafe { Box::from_raw(leaked_boxed_progress) }; + success } pub fn save_auto_snapshot(&self) -> bool { @@ -283,15 +288,17 @@ impl FileMetadata { ) -> Result, ()> { let filename = filename.into_bytes_with_nul(); let filename_ptr = filename.as_ref().as_ptr() as *mut _; - + let boxed_progress = Box::new(progress.into()); + let leaked_boxed_progress = Box::into_raw(boxed_progress); let view = unsafe { BNOpenExistingDatabaseWithProgress( self.handle, filename_ptr, - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, Some(ProgressExecutor::cb_execute), ) }; + let _ = unsafe { Box::from_raw(leaked_boxed_progress) }; if view.is_null() { Err(()) diff --git a/rust/src/headless.rs b/rust/src/headless.rs index 02e918fb0..6613bf908 100644 --- a/rust/src/headless.rs +++ b/rust/src/headless.rs @@ -21,7 +21,7 @@ use std::path::{Path, PathBuf}; use thiserror::Error; use crate::enterprise::release_license; -use crate::mainthread::{MainThreadAction, MainThreadHandler}; +use crate::main_thread::{MainThreadAction, MainThreadHandler}; use crate::rc::Ref; use binaryninjacore_sys::{BNInitPlugins, BNInitRepoPlugins}; use std::sync::mpsc::Sender; diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 06f0381fc..9499fd512 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -73,11 +73,11 @@ pub mod interaction; pub mod linear_view; pub mod logger; pub mod low_level_il; -pub mod mainthread; +pub mod main_thread; pub mod medium_level_il; pub mod metadata; pub mod platform; -mod progress; +pub mod progress; pub mod project; pub mod rc; pub mod references; @@ -134,15 +134,18 @@ pub fn load_with_progress( ) -> Option> { let file_path = file_path.as_ref().into_bytes_with_nul(); let options = c""; + let boxed_progress = Box::new(progress.into()); + let leaked_boxed_progress = Box::into_raw(boxed_progress); let handle = unsafe { BNLoadFilename( file_path.as_ptr() as *mut _, true, options.as_ptr() as *mut c_char, Some(ProgressExecutor::cb_execute), - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, ) }; + let _ = unsafe { Box::from_raw(leaked_boxed_progress) }; if handle.is_null() { None } else { @@ -206,16 +209,18 @@ where .as_ref() .to_vec() }; - + let boxed_progress = Box::new(progress.into()); + let leaked_boxed_progress = Box::into_raw(boxed_progress); let handle = unsafe { BNLoadFilename( file_path.as_ptr() as *mut _, update_analysis_and_wait, options_or_default.as_ptr() as *mut c_char, Some(ProgressExecutor::cb_execute), - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, ) }; + let _ = unsafe { Box::from_raw(leaked_boxed_progress) }; if handle.is_null() { None @@ -262,16 +267,18 @@ where .as_ref() .to_vec() }; - + let boxed_progress = Box::new(progress.into()); + let leaked_boxed_progress = Box::into_raw(boxed_progress); let handle = unsafe { BNLoadBinaryView( bv.handle as *mut _, update_analysis_and_wait, options_or_default.as_ptr() as *mut c_char, Some(ProgressExecutor::cb_execute), - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, ) }; + let _ = unsafe { Box::from_raw(leaked_boxed_progress) }; if handle.is_null() { None diff --git a/rust/src/mainthread.rs b/rust/src/main_thread.rs similarity index 100% rename from rust/src/mainthread.rs rename to rust/src/main_thread.rs diff --git a/rust/src/medium_level_il/function.rs b/rust/src/medium_level_il/function.rs index c24f862c0..c7a53b601 100644 --- a/rust/src/medium_level_il/function.rs +++ b/rust/src/medium_level_il/function.rs @@ -187,7 +187,7 @@ impl MediumLevelILFunction { /// /// # Example /// ```no_run - /// # use binaryninja::mlil::MediumLevelILFunction; + /// # use binaryninja::medium_level_il::MediumLevelILFunction; /// # use binaryninja::variable::PossibleValueSet; /// # let mlil_fun: MediumLevelILFunction = todo!(); /// let user_var_val = mlil_fun.user_var_values().iter().next().unwrap(); @@ -322,7 +322,7 @@ impl MediumLevelILFunction { /// /// # Example /// ```no_run - /// # use binaryninja::mlil::MediumLevelILFunction; + /// # use binaryninja::medium_level_il::MediumLevelILFunction; /// # use binaryninja::variable::Variable; /// # let mlil_fun: MediumLevelILFunction = todo!(); /// # let mlil_var: Variable = todo!(); diff --git a/rust/src/progress.rs b/rust/src/progress.rs index 7a4391162..605910e82 100644 --- a/rust/src/progress.rs +++ b/rust/src/progress.rs @@ -11,17 +11,12 @@ impl ProgressExecutor { } } - /// Leak the executor and return an opaque pointer. - pub fn into_raw_context(self) -> *mut c_void { - Box::into_raw(Box::new(self)) as *mut c_void - } - pub unsafe extern "C" fn cb_execute(ctx: *mut c_void, progress: usize, total: usize) -> bool { if ctx.is_null() { return true; } - let f: Box = Box::from_raw(ctx as *mut Self); - f.execute(progress, total) + let executor: *mut Self = ctx as *mut Self; + (*executor).execute(progress, total) } pub fn execute(&self, progress: usize, total: usize) -> bool { diff --git a/rust/src/project.rs b/rust/src/project.rs index 49bd32c82..3e8b45a41 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; +use std::ffi::{c_char, c_void}; use std::fmt::Debug; use std::ptr::{null_mut, NonNull}; use std::time::{Duration, SystemTime, UNIX_EPOCH}; @@ -39,7 +39,7 @@ impl Project { /// /// * `path` - Path to the project directory (.bnpr) /// * `name` - Name of the new project - pub fn create(path: P, name: S) -> Ref { + 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 { @@ -48,16 +48,16 @@ impl Project { name_raw.as_ref().as_ptr() as *const c_char, ) }; - unsafe { Self::ref_from_raw(NonNull::new(handle).unwrap()) } + 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) -> Ref { + 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) }; - unsafe { Self::ref_from_raw(NonNull::new(handle).unwrap()) } + NonNull::new(handle).map(|h| unsafe { Self::ref_from_raw(h) }) } /// Check if the project is currently open @@ -207,16 +207,18 @@ impl Project { let path_raw = path.into_bytes_with_nul(); let description_raw = description.into_bytes_with_nul(); let parent_ptr = parent.map(|p| p.handle.as_ptr()).unwrap_or(null_mut()); - + let boxed_progress = Box::new(progress.into()); + let leaked_boxed_progress = Box::into_raw(boxed_progress); unsafe { let result = BNProjectCreateFolderFromPath( self.handle.as_ptr(), path_raw.as_ref().as_ptr() as *const c_char, parent_ptr, description_raw.as_ref().as_ptr() as *const c_char, - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, Some(ProgressExecutor::cb_execute), ); + let _ = Box::from_raw(leaked_boxed_progress); Ok(ProjectFolder::ref_from_raw(NonNull::new(result).ok_or(())?)) } } @@ -320,14 +322,17 @@ impl Project { folder: &ProjectFolder, progress: impl Into, ) -> Result<(), ()> { + let boxed_progress = Box::new(progress.into()); + let leaked_boxed_progress = Box::into_raw(boxed_progress); let result = unsafe { BNProjectDeleteFolder( self.handle.as_ptr(), folder.handle.as_ptr(), - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, Some(ProgressExecutor::cb_execute), ) }; + let _ = unsafe { Box::from_raw(leaked_boxed_progress) }; if result { Ok(()) } else { @@ -390,6 +395,8 @@ impl Project { let name_raw = name.into_bytes_with_nul(); let description_raw = description.into_bytes_with_nul(); let folder_ptr = folder.map(|p| p.handle.as_ptr()).unwrap_or(null_mut()); + let boxed_progress = Box::new(progress.into()); + let leaked_boxed_progress = Box::into_raw(boxed_progress); unsafe { let result = BNProjectCreateFileFromPath( self.handle.as_ptr(), @@ -397,9 +404,10 @@ impl Project { folder_ptr, name_raw.as_ref().as_ptr() as *const c_char, description_raw.as_ref().as_ptr() as *const c_char, - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, Some(ProgressExecutor::cb_execute), ); + let _ = Box::from_raw(leaked_boxed_progress); Ok(ProjectFile::ref_from_raw(NonNull::new(result).ok_or(())?)) } } @@ -469,6 +477,8 @@ impl Project { let description_raw = description.into_bytes_with_nul(); let id_raw = id.into_bytes_with_nul(); let folder_ptr = folder.map(|p| p.handle.as_ptr()).unwrap_or(null_mut()); + let boxed_progress = Box::new(progress.into()); + let leaked_boxed_progress = Box::into_raw(boxed_progress); unsafe { let result = BNProjectCreateFileFromPathUnsafe( self.handle.as_ptr(), @@ -478,9 +488,10 @@ impl Project { description_raw.as_ref().as_ptr() as *const c_char, id_raw.as_ref().as_ptr() as *const c_char, systime_to_bntime(creation_time).unwrap(), - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, Some(ProgressExecutor::cb_execute), ); + let _ = Box::from_raw(leaked_boxed_progress); Ok(ProjectFile::ref_from_raw(NonNull::new(result).ok_or(())?)) } } @@ -533,6 +544,8 @@ impl Project { let name_raw = name.into_bytes_with_nul(); let description_raw = description.into_bytes_with_nul(); let folder_ptr = folder.map(|p| p.handle.as_ptr()).unwrap_or(null_mut()); + let boxed_progress = Box::new(progress.into()); + let leaked_boxed_progress = Box::into_raw(boxed_progress); unsafe { let result = BNProjectCreateFile( self.handle.as_ptr(), @@ -541,9 +554,10 @@ impl Project { folder_ptr, name_raw.as_ref().as_ptr() as *const c_char, description_raw.as_ref().as_ptr() as *const c_char, - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, Some(ProgressExecutor::cb_execute), ); + let _ = Box::from_raw(leaked_boxed_progress); Ok(ProjectFile::ref_from_raw(NonNull::new(result).ok_or(())?)) } } @@ -610,6 +624,8 @@ impl Project { let description_raw = description.into_bytes_with_nul(); let id_raw = id.into_bytes_with_nul(); let folder_ptr = folder.map(|p| p.handle.as_ptr()).unwrap_or(null_mut()); + let boxed_progress = Box::new(progress.into()); + let leaked_boxed_progress = Box::into_raw(boxed_progress); unsafe { let result = BNProjectCreateFileUnsafe( self.handle.as_ptr(), @@ -620,19 +636,20 @@ impl Project { description_raw.as_ref().as_ptr() as *const c_char, id_raw.as_ref().as_ptr() as *const c_char, systime_to_bntime(creation_time).unwrap(), - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, Some(ProgressExecutor::cb_execute), ); + let _ = Box::from_raw(leaked_boxed_progress); Ok(ProjectFile::ref_from_raw(NonNull::new(result).ok_or(())?)) } } /// Get a list of files in the project - pub fn files(&self) -> Result, ()> { + pub fn files(&self) -> Array { let mut count = 0; let result = unsafe { BNProjectGetFiles(self.handle.as_ptr(), &mut count) }; assert!(!result.is_null()); - Ok(unsafe { Array::new(result, count, ()) }) + unsafe { Array::new(result, count, ()) } } /// Retrieve a file in the project by unique `id` diff --git a/rust/src/project/file.rs b/rust/src/project/file.rs index dfa19a7dc..5071dd50b 100644 --- a/rust/src/project/file.rs +++ b/rust/src/project/file.rs @@ -90,9 +90,9 @@ impl ProjectFile { } /// Get the folder that contains this file - pub fn folder(&self) -> Option { + pub fn folder(&self) -> Option> { let result = unsafe { BNProjectFileGetFolder(self.handle.as_ptr()) }; - NonNull::new(result).map(|handle| unsafe { ProjectFolder::from_raw(handle) }) + NonNull::new(result).map(|handle| unsafe { ProjectFolder::ref_from_raw(handle) }) } /// Set the folder that contains this file diff --git a/rust/src/project/folder.rs b/rust/src/project/folder.rs index 01d9f992a..ea2789dd3 100644 --- a/rust/src/project/folder.rs +++ b/rust/src/project/folder.rs @@ -8,7 +8,7 @@ use binaryninjacore_sys::{ BNProjectFolderGetName, BNProjectFolderGetParent, BNProjectFolderGetProject, BNProjectFolderSetDescription, BNProjectFolderSetName, BNProjectFolderSetParent, }; -use std::ffi::c_char; +use std::ffi::{c_char, c_void}; use std::fmt::Debug; use std::ptr::{null_mut, NonNull}; @@ -27,9 +27,9 @@ impl ProjectFolder { } /// Get the project that owns this folder - pub fn project(&self) -> Project { + pub fn project(&self) -> Ref { unsafe { - Project::from_raw( + Project::ref_from_raw( NonNull::new(BNProjectFolderGetProject(self.handle.as_ptr())).unwrap(), ) } @@ -102,14 +102,18 @@ impl ProjectFolder { S: BnStrCompatible, { let dest_raw = dest.into_bytes_with_nul(); - unsafe { + let boxed_progress = Box::new(progress.into()); + let leaked_boxed_progress = Box::into_raw(boxed_progress); + let success = unsafe { BNProjectFolderExport( self.handle.as_ptr(), dest_raw.as_ref().as_ptr() as *const c_char, - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, Some(ProgressExecutor::cb_execute), ) - } + }; + let _ = unsafe { Box::from_raw(leaked_boxed_progress) }; + success } } diff --git a/rust/src/type_archive.rs b/rust/src/type_archive.rs index 1930b3372..8d2671580 100644 --- a/rust/src/type_archive.rs +++ b/rust/src/type_archive.rs @@ -836,7 +836,8 @@ impl TypeArchive { let mut conflicts_errors_count = 0; let mut result = std::ptr::null_mut(); - + let boxed_progress = Box::new(progress.into()); + let leaked_boxed_progress = Box::into_raw(boxed_progress); let success = unsafe { BNTypeArchiveMergeSnapshots( self.handle.as_ptr(), @@ -850,9 +851,10 @@ impl TypeArchive { &mut conflicts_errors_count, &mut result, Some(ProgressExecutor::cb_execute), - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, ) }; + let _ = unsafe { Box::from_raw(leaked_boxed_progress) }; if success { assert!(!result.is_null()); Ok(unsafe { BnString::from_raw(result) }) diff --git a/rust/src/type_container.rs b/rust/src/type_container.rs index 1aa578804..e060d87b9 100644 --- a/rust/src/type_container.rs +++ b/rust/src/type_container.rs @@ -16,7 +16,7 @@ use crate::type_parser::{TypeParserError, TypeParserResult}; use crate::types::{QualifiedName, QualifiedNameAndType, Type}; use binaryninjacore_sys::*; use std::collections::HashMap; -use std::ffi::c_char; +use std::ffi::{c_char, c_void}; use std::fmt::{Debug, Formatter}; use std::ptr::NonNull; @@ -113,6 +113,8 @@ impl TypeContainer { let mut result_names = std::ptr::null_mut(); let mut result_ids = std::ptr::null_mut(); let mut result_count = 0; + let boxed_progress = Box::new(progress.into()); + let leaked_boxed_progress = Box::into_raw(boxed_progress); let success = unsafe { BNTypeContainerAddTypes( self.handle.as_ptr(), @@ -120,12 +122,13 @@ impl TypeContainer { raw_types.as_mut_ptr(), raw_types.len(), Some(ProgressExecutor::cb_execute), - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, &mut result_names, &mut result_ids, &mut result_count, ) }; + let _ = unsafe { Box::from_raw(leaked_boxed_progress) }; for name in raw_names { QualifiedName::free_raw(name); } diff --git a/rust/src/update.rs b/rust/src/update.rs index 85f5002dd..db930b2d5 100644 --- a/rust/src/update.rs +++ b/rust/src/update.rs @@ -1,5 +1,5 @@ #![allow(dead_code)] -use std::ffi::c_char; +use std::ffi::{c_char, c_void}; use std::time::{Duration, SystemTime, UNIX_EPOCH}; use crate::progress::ProgressExecutor; @@ -146,14 +146,17 @@ impl UpdateChannel { progress: impl Into, ) -> Result { let mut errors = std::ptr::null_mut(); + let boxed_progress = Box::new(progress.into()); + let leaked_boxed_progress = Box::into_raw(boxed_progress); let result = unsafe { BNUpdateToLatestVersion( self.name.as_ptr() as *const c_char, &mut errors, Some(ProgressExecutor::cb_execute), - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, ) }; + let _ = unsafe { Box::from_raw(leaked_boxed_progress) }; if !errors.is_null() { Err(unsafe { BnString::from_raw(errors) }) } else { @@ -171,15 +174,18 @@ impl UpdateChannel { progress: impl Into, ) -> Result { let mut errors = std::ptr::null_mut(); + let boxed_progress = Box::new(progress.into()); + let leaked_boxed_progress = Box::into_raw(boxed_progress); let result = unsafe { BNUpdateToVersion( self.name.as_ptr() as *const c_char, version.version.as_ptr() as *const c_char, &mut errors, Some(ProgressExecutor::cb_execute), - progress.into().into_raw_context(), + leaked_boxed_progress as *mut c_void, ) }; + let _ = unsafe { Box::from_raw(leaked_boxed_progress) }; if !errors.is_null() { Err(unsafe { BnString::from_raw(errors) }) } else { diff --git a/rust/tests/mainthread.rs b/rust/tests/mainthread.rs index 3ca236f81..f74414d55 100644 --- a/rust/tests/mainthread.rs +++ b/rust/tests/mainthread.rs @@ -18,7 +18,7 @@ fn test_not_main_thread(_session: &Session) { #[rstest] fn test_main_thread_different(_session: &Session) { let calling_thread = std::thread::current(); - binaryninja::mainthread::execute_on_main_thread_and_wait(move || { + binaryninja::main_thread::execute_on_main_thread_and_wait(move || { let main_thread = std::thread::current(); assert_ne!( calling_thread.id(), diff --git a/rust/tests/project.rs b/rust/tests/project.rs index 9f757f2fe..cc41c11e6 100644 --- a/rust/tests/project.rs +++ b/rust/tests/project.rs @@ -24,7 +24,7 @@ fn create_delete_empty(_session: &Session) { let project_name = "create_delete_empty_project"; let project_path = unique_project(project_name); // create the project - let project = Project::create(&project_path, project_name); + let project = Project::create(&project_path, project_name).expect("Failed to create project"); project.open().unwrap(); assert!(project.is_open()); @@ -51,7 +51,7 @@ fn create_close_open_close(_session: &Session) { let project_name = "create_close_open_close"; let project_path = unique_project(project_name); // create the project - let project = Project::create(&project_path, project_name); + let project = Project::create(&project_path, project_name).expect("Failed to create project"); project.open().unwrap(); // get the project id @@ -61,7 +61,7 @@ fn create_close_open_close(_session: &Session) { project.close().unwrap(); drop(project); - let project = Project::open_project(&project_path); + let project = Project::open_project(&project_path).expect("Failed to open project"); // assert same id let new_id = project.id(); assert_eq!(id, new_id); @@ -76,10 +76,10 @@ fn create_close_open_close(_session: &Session) { #[rstest] fn modify_project(_session: &Session) { - let project_name = "modify_project"; + let project_name = "modify_project_project"; let project_path = unique_project(project_name); // create the project - let project = Project::create(&project_path, project_name); + let project = Project::create(&project_path, project_name).expect("Failed to create project"); project.open().unwrap(); // get project id @@ -248,12 +248,12 @@ fn modify_project(_session: &Session) { } .unwrap(); - assert_eq!(project.files().unwrap().len(), 10); + assert_eq!(project.files().len(), 10); let file_a = project.file_by_id(file_8.id()).unwrap(); let file_b = project.file_by_path(file_7.path_on_disk()).unwrap(); project.delete_file(&file_a); project.delete_file(&file_b); - assert_eq!(project.files().unwrap().len(), 8); + assert_eq!(project.files().len(), 8); drop(file_8); drop(file_7); @@ -268,7 +268,7 @@ fn modify_project(_session: &Session) { drop(folder_3); // reopen the project and verify the information store on it - let project = Project::open_project(&project_path); + let project = Project::open_project(&project_path).expect("Failed to open project"); // assert same id assert_eq!(id, project.id()); @@ -317,7 +317,7 @@ fn modify_project(_session: &Session) { ("input_1", &input_file_1_data[..], None, None), ("input_2", &input_file_2_data[..], None, None), ]; - for file in project.files().unwrap().iter() { + for file in project.files().iter() { let found = files.iter().find(|f| file.name().as_str() == f.0).unwrap(); if let Some(id) = found.2 { assert_eq!(file.id().as_str(), id);