From 17985a350050254f6731901fb7631f5dcbd1fcb8 Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Wed, 29 May 2024 07:56:33 -0300 Subject: [PATCH 01/33] change `TypeBuilder` to the new standard --- rust/src/types.rs | 189 ++++++++++++++++++++++++++++++---------------- 1 file changed, 123 insertions(+), 66 deletions(-) diff --git a/rust/src/types.rs b/rust/src/types.rs index 29cdb2d3d..9835690e1 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -41,7 +41,8 @@ use std::{ mem::{self, ManuallyDrop}, ops::Range, os::raw::c_char, - ptr, result, slice, + ptr::{self, NonNull}, + result, slice, sync::Mutex, }; @@ -304,84 +305,88 @@ impl From> for BNOffsetWithConfidence { ////////////////// // Type Builder +#[repr(transparent)] #[derive(PartialEq, Eq, Hash)] pub struct TypeBuilder { - pub(crate) handle: *mut BNTypeBuilder, + pub(crate) handle: NonNull, } impl TypeBuilder { pub fn new(t: &Type) -> Self { - unsafe { Self::from_raw(BNCreateTypeBuilderFromType(t.handle)) } + unsafe { Self::from_raw(NonNull::new(BNCreateTypeBuilderFromType(t.handle)).unwrap()) } } - pub(crate) unsafe fn from_raw(handle: *mut BNTypeBuilder) -> Self { - debug_assert!(!handle.is_null()); + pub(crate) unsafe fn from_raw(handle: NonNull) -> Self { Self { handle } } + pub(crate) fn as_raw(&self) -> &mut BNTypeBuilder { + unsafe { &mut (*self.handle.as_ptr()) } + } + // Chainable terminal pub fn finalize(&self) -> Ref { - unsafe { Type::ref_from_raw(BNFinalizeTypeBuilder(self.handle)) } + unsafe { Type::ref_from_raw(BNFinalizeTypeBuilder(self.as_raw())) } } // Settable properties pub fn set_can_return>>(&self, value: T) -> &Self { let mut bool_with_confidence = value.into().into(); - unsafe { BNSetFunctionTypeBuilderCanReturn(self.handle, &mut bool_with_confidence) }; + unsafe { BNSetFunctionTypeBuilderCanReturn(self.as_raw(), &mut bool_with_confidence) }; self } pub fn set_pure>>(&self, value: T) -> &Self { let mut bool_with_confidence = value.into().into(); - unsafe { BNSetTypeBuilderPure(self.handle, &mut bool_with_confidence) }; + unsafe { BNSetTypeBuilderPure(self.as_raw(), &mut bool_with_confidence) }; self } pub fn set_const>>(&self, value: T) -> &Self { let mut bool_with_confidence = value.into().into(); - unsafe { BNTypeBuilderSetConst(self.handle, &mut bool_with_confidence) }; + unsafe { BNTypeBuilderSetConst(self.as_raw(), &mut bool_with_confidence) }; self } pub fn set_volatile>>(&self, value: T) -> &Self { let mut bool_with_confidence = value.into().into(); - unsafe { BNTypeBuilderSetVolatile(self.handle, &mut bool_with_confidence) }; + unsafe { BNTypeBuilderSetVolatile(self.as_raw(), &mut bool_with_confidence) }; self } // Readable properties pub fn type_class(&self) -> TypeClass { - unsafe { BNGetTypeBuilderClass(self.handle) } + unsafe { BNGetTypeBuilderClass(self.as_raw()) } } pub fn width(&self) -> u64 { - unsafe { BNGetTypeBuilderWidth(self.handle) } + unsafe { BNGetTypeBuilderWidth(self.as_raw()) } } pub fn alignment(&self) -> usize { - unsafe { BNGetTypeBuilderAlignment(self.handle) } + unsafe { BNGetTypeBuilderAlignment(self.as_raw()) } } pub fn is_signed(&self) -> Conf { - unsafe { BNIsTypeBuilderSigned(self.handle).into() } + unsafe { BNIsTypeBuilderSigned(self.as_raw()).into() } } pub fn is_const(&self) -> Conf { - unsafe { BNIsTypeBuilderConst(self.handle).into() } + unsafe { BNIsTypeBuilderConst(self.as_raw()).into() } } pub fn is_volatile(&self) -> Conf { - unsafe { BNIsTypeBuilderVolatile(self.handle).into() } + unsafe { BNIsTypeBuilderVolatile(self.as_raw()).into() } } pub fn is_floating_point(&self) -> bool { - unsafe { BNIsTypeBuilderFloatingPoint(self.handle) } + unsafe { BNIsTypeBuilderFloatingPoint(self.as_raw()) } } pub fn target(&self) -> Result>> { - let raw_target = unsafe { BNGetTypeBuilderChildType(self.handle) }; + let raw_target = unsafe { BNGetTypeBuilderChildType(self.as_raw()) }; if raw_target.type_.is_null() { Err(()) } else { @@ -390,7 +395,7 @@ impl TypeBuilder { } pub fn element_type(&self) -> Result>> { - let raw_target = unsafe { BNGetTypeBuilderChildType(self.handle) }; + let raw_target = unsafe { BNGetTypeBuilderChildType(self.as_raw()) }; if raw_target.type_.is_null() { Err(()) } else { @@ -399,7 +404,7 @@ impl TypeBuilder { } pub fn return_value(&self) -> Result>> { - let raw_target = unsafe { BNGetTypeBuilderChildType(self.handle) }; + let raw_target = unsafe { BNGetTypeBuilderChildType(self.as_raw()) }; if raw_target.type_.is_null() { Err(()) } else { @@ -408,7 +413,7 @@ impl TypeBuilder { } pub fn calling_convention(&self) -> Result>>> { - let convention_confidence = unsafe { BNGetTypeBuilderCallingConvention(self.handle) }; + let convention_confidence = unsafe { BNGetTypeBuilderCallingConvention(self.as_raw()) }; if convention_confidence.convention.is_null() { Err(()) } else { @@ -419,7 +424,7 @@ impl TypeBuilder { pub fn parameters(&self) -> Result> { unsafe { let mut count = 0; - let parameters_raw = BNGetTypeBuilderParameters(self.handle, &mut count); + let parameters_raw = BNGetTypeBuilderParameters(self.as_raw(), &mut count); if parameters_raw.is_null() { Err(()) } else { @@ -438,19 +443,19 @@ impl TypeBuilder { } pub fn has_variable_arguments(&self) -> Conf { - unsafe { BNTypeBuilderHasVariableArguments(self.handle).into() } + unsafe { BNTypeBuilderHasVariableArguments(self.as_raw()).into() } } pub fn can_return(&self) -> Conf { - unsafe { BNFunctionTypeBuilderCanReturn(self.handle).into() } + unsafe { BNFunctionTypeBuilderCanReturn(self.as_raw()).into() } } pub fn pure(&self) -> Conf { - unsafe { BNIsTypeBuilderPure(self.handle).into() } + unsafe { BNIsTypeBuilderPure(self.as_raw()).into() } } pub fn get_structure(&self) -> Result> { - let result = unsafe { BNGetTypeBuilderStructure(self.handle) }; + let result = unsafe { BNGetTypeBuilderStructure(self.as_raw()) }; if result.is_null() { Err(()) } else { @@ -459,7 +464,7 @@ impl TypeBuilder { } pub fn get_enumeration(&self) -> Result> { - let result = unsafe { BNGetTypeBuilderEnumeration(self.handle) }; + let result = unsafe { BNGetTypeBuilderEnumeration(self.as_raw()) }; if result.is_null() { Err(()) } else { @@ -468,7 +473,7 @@ impl TypeBuilder { } pub fn get_named_type_reference(&self) -> Result> { - let result = unsafe { BNGetTypeBuilderNamedTypeReference(self.handle) }; + let result = unsafe { BNGetTypeBuilderNamedTypeReference(self.as_raw()) }; if result.is_null() { Err(()) } else { @@ -477,26 +482,26 @@ impl TypeBuilder { } pub fn count(&self) -> u64 { - unsafe { BNGetTypeBuilderElementCount(self.handle) } + unsafe { BNGetTypeBuilderElementCount(self.as_raw()) } } pub fn offset(&self) -> u64 { - unsafe { BNGetTypeBuilderOffset(self.handle) } + unsafe { BNGetTypeBuilderOffset(self.as_raw()) } } pub fn stack_adjustment(&self) -> Conf { - unsafe { BNGetTypeBuilderStackAdjustment(self.handle).into() } + unsafe { BNGetTypeBuilderStackAdjustment(self.as_raw()).into() } } // TODO : This and properties // pub fn tokens(&self) -> ? {} pub fn void() -> Self { - unsafe { Self::from_raw(BNCreateVoidTypeBuilder()) } + unsafe { Self::from_raw(NonNull::new(BNCreateVoidTypeBuilder()).unwrap()) } } pub fn bool() -> Self { - unsafe { Self::from_raw(BNCreateBoolTypeBuilder()) } + unsafe { Self::from_raw(NonNull::new(BNCreateBoolTypeBuilder()).unwrap()) } } pub fn char() -> Self { @@ -507,11 +512,12 @@ impl TypeBuilder { let mut is_signed = Conf::new(is_signed, max_confidence()).into(); unsafe { - Self::from_raw(BNCreateIntegerTypeBuilder( + let result = BNCreateIntegerTypeBuilder( width, &mut is_signed, BnString::new("").as_ptr() as *mut _, - )) + ); + Self::from_raw(NonNull::new(result).unwrap()) } } @@ -521,20 +527,16 @@ impl TypeBuilder { let alt_name = alt_name.into_bytes_with_nul(); // This segfaulted once, so the above version is there if we need to change to it, but in theory this is copied into a `const string&` on the C++ side; I'm just not 100% confident that a constant reference copies data unsafe { - Self::from_raw(BNCreateIntegerTypeBuilder( - width, - &mut is_signed, - alt_name.as_ref().as_ptr() as _, - )) + let result = + BNCreateIntegerTypeBuilder(width, &mut is_signed, alt_name.as_ref().as_ptr() as _); + Self::from_raw(NonNull::new(result).unwrap()) } } pub fn float(width: usize) -> Self { unsafe { - Self::from_raw(BNCreateFloatTypeBuilder( - width, - BnString::new("").as_ptr() as *mut _, - )) + let result = BNCreateFloatTypeBuilder(width, BnString::new("").as_ptr() as *mut _); + Self::from_raw(NonNull::new(result).unwrap()) } } @@ -543,15 +545,15 @@ impl TypeBuilder { let alt_name = alt_name.into_bytes_with_nul(); // See same line in `named_int` above unsafe { - Self::from_raw(BNCreateFloatTypeBuilder( - width, - alt_name.as_ref().as_ptr() as _, - )) + let result = BNCreateFloatTypeBuilder(width, alt_name.as_ref().as_ptr() as _); + Self::from_raw(NonNull::new(result).unwrap()) } } pub fn array<'a, T: Into>>(t: T, count: u64) -> Self { - unsafe { Self::from_raw(BNCreateArrayTypeBuilder(&t.into().into(), count)) } + unsafe { + Self::from_raw(NonNull::new(BNCreateArrayTypeBuilder(&t.into().into(), count)).unwrap()) + } } /// The C/C++ APIs require an associated architecture, but in the core we only query the default_int_size if the given width is 0 @@ -564,30 +566,36 @@ impl TypeBuilder { unsafe { // TODO : This is _extremely fragile_, we should change the internals of BNCreateEnumerationTypeBuilder instead of doing this let mut fake_arch: BNArchitecture = mem::zeroed(); - Self::from_raw(BNCreateEnumerationTypeBuilder( + let result = BNCreateEnumerationTypeBuilder( &mut fake_arch, enumeration.handle, width, &mut is_signed.into().into(), - )) + ); + Self::from_raw(NonNull::new(result).unwrap()) } } pub fn structure(structure_type: &Structure) -> Self { - unsafe { Self::from_raw(BNCreateStructureTypeBuilder(structure_type.handle)) } + unsafe { + Self::from_raw( + NonNull::new(BNCreateStructureTypeBuilder(structure_type.handle)).unwrap(), + ) + } } pub fn named_type(type_reference: NamedTypeReference) -> Self { let mut is_const = Conf::new(false, min_confidence()).into(); let mut is_volatile = Conf::new(false, min_confidence()).into(); unsafe { - Self::from_raw(BNCreateNamedTypeReferenceBuilder( + let result = BNCreateNamedTypeReferenceBuilder( type_reference.handle, 0, 1, &mut is_const, &mut is_volatile, - )) + ); + Self::from_raw(NonNull::new(result).unwrap()) } } @@ -595,11 +603,12 @@ impl TypeBuilder { let mut name = QualifiedName::from(name); unsafe { - Self::from_raw(BNCreateNamedTypeReferenceBuilderFromTypeAndId( + let result = BNCreateNamedTypeReferenceBuilderFromTypeAndId( BnString::new("").as_ptr() as *mut _, &mut name.0, t.handle, - )) + ); + Self::from_raw(NonNull::new(result).unwrap()) } } @@ -610,13 +619,14 @@ impl TypeBuilder { let mut is_volatile = Conf::new(false, min_confidence()).into(); unsafe { - Self::from_raw(BNCreatePointerTypeBuilder( + let result = BNCreatePointerTypeBuilder( arch.as_ref().0, &t.into().into(), &mut is_const, &mut is_volatile, ReferenceType::PointerReferenceType, - )) + ); + Self::from_raw(NonNull::new(result).unwrap()) } } @@ -625,13 +635,14 @@ impl TypeBuilder { let mut is_volatile = Conf::new(false, min_confidence()).into(); unsafe { - Self::from_raw(BNCreatePointerTypeBuilder( + let result = BNCreatePointerTypeBuilder( arch.as_ref().0, &t.into().into(), &mut is_const, &mut is_volatile, ReferenceType::PointerReferenceType, - )) + ); + Self::from_raw(NonNull::new(result).unwrap()) } } @@ -646,13 +657,14 @@ impl TypeBuilder { let mut is_volatile = Conf::new(is_volatile, max_confidence()).into(); unsafe { - Self::from_raw(BNCreatePointerTypeBuilderOfWidth( + let result = BNCreatePointerTypeBuilderOfWidth( size, &t.into().into(), &mut is_const, &mut is_volatile, ref_type.unwrap_or(ReferenceType::PointerReferenceType), - )) + ); + Self::from_raw(NonNull::new(result).unwrap()) } } @@ -666,13 +678,14 @@ impl TypeBuilder { let mut is_const = Conf::new(is_const, max_confidence()).into(); let mut is_volatile = Conf::new(is_volatile, max_confidence()).into(); unsafe { - Self::from_raw(BNCreatePointerTypeBuilder( + let result = BNCreatePointerTypeBuilder( arch.as_ref().0, &t.into().into(), &mut is_const, &mut is_volatile, ref_type.unwrap_or(ReferenceType::PointerReferenceType), - )) + ); + Self::from_raw(NonNull::new(result).unwrap()) } } } @@ -680,14 +693,14 @@ impl TypeBuilder { impl fmt::Display for TypeBuilder { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", unsafe { - BnString::from_raw(BNGetTypeBuilderString(self.handle, ptr::null_mut())) + BnString::from_raw(BNGetTypeBuilderString(self.as_raw(), ptr::null_mut())) }) } } impl Drop for TypeBuilder { fn drop(&mut self) { - unsafe { BNFreeTypeBuilder(self.handle) }; + unsafe { BNFreeTypeBuilder(self.as_raw()) }; } } @@ -3720,3 +3733,47 @@ unsafe impl CoreArrayProviderInner for UnresolvedIndirectBranches { Self(*raw) } } + +#[cfg(test)] +mod test { + use crate::types::{Conf, FunctionParameter, TypeClass}; + + use super::{Type, TypeBuilder}; + + #[test] + fn create_bool_type() { + let type_builder = TypeBuilder::new(&Type::bool()); + assert_eq!(type_builder.type_class(), TypeClass::BoolTypeClass); + assert_eq!(type_builder.width(), 1); + assert!(type_builder.alignment() <= 1); + //assert_eq!(type_builder.is_signed().contents, true); + assert_eq!(type_builder.is_const().contents, false); + assert_eq!(type_builder.is_floating_point(), false); + assert!(type_builder.return_value().is_err()); + assert!(type_builder.calling_convention().is_err()); + let type_built = type_builder.finalize(); + assert_eq!(type_built, Type::bool()); + } + + #[test] + fn create_function_type() { + let expected_type = Type::function( + &Type::int(4, true), + &[ + FunctionParameter::new(Type::int(4, true), "a".to_string(), None), + FunctionParameter::new(Type::int(4, true), "b".to_string(), None), + ], + false, + ); + let type_builder = TypeBuilder::new(&expected_type); + assert_eq!(type_builder.type_class(), TypeClass::FunctionTypeClass); + assert_eq!(type_builder.is_floating_point(), false); + assert_eq!( + type_builder.return_value().unwrap().contents, + Type::int(4, true) + ); + //assert_eq!(type_builder.calling_convention(), CallingConvention); + let type_built = type_builder.finalize(); + assert_eq!(type_built, expected_type); + } +} From 4146df21f153f10b3bdbe824e12d6b21dbeb52d6 Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Wed, 29 May 2024 09:08:45 -0300 Subject: [PATCH 02/33] change `Type` to the new standard --- rust/src/architecture.rs | 6 +- rust/src/binaryview.rs | 38 ++-- rust/src/callingconvention.rs | 2 +- rust/src/debuginfo.rs | 99 +++++++---- rust/src/demangle.rs | 9 +- rust/src/function.rs | 46 ++--- rust/src/mlil/instruction.rs | 8 +- rust/src/platform.rs | 45 ++--- rust/src/types.rs | 319 +++++++++++++++++----------------- 9 files changed, 315 insertions(+), 257 deletions(-) diff --git a/rust/src/architecture.rs b/rust/src/architecture.rs index cf5d32d64..6ea7d9aac 100644 --- a/rust/src/architecture.rs +++ b/rust/src/architecture.rs @@ -316,7 +316,7 @@ pub trait Intrinsic: Sized + Clone + Copy { fn inputs(&self) -> Vec>; /// Returns the list of the output types for this intrinsic. - fn outputs(&self) -> Vec>>; + fn outputs(&self) -> Vec>; } pub trait Architecture: 'static + Sized + AsRef { @@ -653,7 +653,7 @@ impl Intrinsic for UnusedIntrinsic { fn inputs(&self) -> Vec> { unreachable!() } - fn outputs(&self) -> Vec>> { + fn outputs(&self) -> Vec> { unreachable!() } } @@ -1024,7 +1024,7 @@ impl Intrinsic for crate::architecture::CoreIntrinsic { } } - fn outputs(&self) -> Vec>> { + fn outputs(&self) -> Vec> { let mut count: usize = 0; unsafe { diff --git a/rust/src/binaryview.rs b/rust/src/binaryview.rs index 25b3fbb2f..a4ed3332c 100644 --- a/rust/src/binaryview.rs +++ b/rust/src/binaryview.rs @@ -497,17 +497,15 @@ pub trait BinaryViewExt: BinaryViewBase { } } - fn define_auto_symbol_with_type<'a, T: Into>>( + fn define_auto_symbol_with_type( &self, sym: &Symbol, plat: &Platform, - ty: T, + ty: Option<&Type>, ) -> Result> { - let raw_type = if let Some(t) = ty.into() { - t.handle - } else { - ptr::null_mut() - }; + let raw_type = ty + .map(|t| t.as_raw() as *mut BNType) + .unwrap_or(ptr::null_mut()); unsafe { let raw_sym = BNDefineAutoSymbolAndVariableOrFunction( @@ -594,7 +592,7 @@ pub trait BinaryViewExt: BinaryViewBase { self.as_ref().handle, id_str, &mut qualified_name.0, - type_obj.handle, + type_obj.as_raw(), ) }; QualifiedName(name_handle) @@ -603,7 +601,11 @@ pub trait BinaryViewExt: BinaryViewBase { fn define_user_type(&self, name: S, type_obj: &Type) { let mut qualified_name = QualifiedName::from(name); unsafe { - BNDefineUserAnalysisType(self.as_ref().handle, &mut qualified_name.0, type_obj.handle) + BNDefineUserAnalysisType( + self.as_ref().handle, + &mut qualified_name.0, + type_obj.as_raw(), + ) } } @@ -627,7 +629,7 @@ pub trait BinaryViewExt: BinaryViewBase { api_types.push(BNQualifiedNameTypeAndId { name: name.0, id: source.as_ref().as_ptr() as *mut _, - type_: type_obj.handle, + type_: type_obj.as_raw(), }); } @@ -674,7 +676,7 @@ pub trait BinaryViewExt: BinaryViewBase { for (name, type_obj) in names.iter().zip(types.iter()) { api_types.push(BNQualifiedNameAndType { name: name.0, - type_: type_obj.handle, + type_: type_obj.as_raw(), }); } @@ -718,28 +720,28 @@ pub trait BinaryViewExt: BinaryViewBase { } } - fn get_type_by_name(&self, name: S) -> Option> { + fn get_type_by_name(&self, name: S) -> Option { unsafe { let mut qualified_name = QualifiedName::from(name); let type_handle = BNGetAnalysisTypeByName(self.as_ref().handle, &mut qualified_name.0); if type_handle.is_null() { return None; } - Some(Type::ref_from_raw(type_handle)) + Some(Type::from_raw(ptr::NonNull::new(type_handle).unwrap())) } } - fn get_type_by_ref(&self, ref_: &NamedTypeReference) -> Option> { + fn get_type_by_ref(&self, ref_: &NamedTypeReference) -> Option { unsafe { let type_handle = BNGetAnalysisTypeByRef(self.as_ref().handle, ref_.handle); if type_handle.is_null() { return None; } - Some(Type::ref_from_raw(type_handle)) + Some(Type::from_raw(ptr::NonNull::new(type_handle).unwrap())) } } - fn get_type_by_id(&self, id: S) -> Option> { + fn get_type_by_id(&self, id: S) -> Option { unsafe { let id_str = id.into_bytes_with_nul(); let type_handle = @@ -747,7 +749,7 @@ pub trait BinaryViewExt: BinaryViewBase { if type_handle.is_null() { return None; } - Some(Type::ref_from_raw(type_handle)) + Some(Type::from_raw(ptr::NonNull::new(type_handle).unwrap())) } } @@ -888,7 +890,7 @@ pub trait BinaryViewExt: BinaryViewBase { ) -> Option> { unsafe { let func_type = match func_type { - Some(func_type) => func_type.handle, + Some(func_type) => func_type.as_raw(), None => ptr::null_mut(), }; diff --git a/rust/src/callingconvention.rs b/rust/src/callingconvention.rs index e7888131b..9732e52f7 100644 --- a/rust/src/callingconvention.rs +++ b/rust/src/callingconvention.rs @@ -455,7 +455,7 @@ impl CallingConvention { }; bn_params.push(BNFunctionParameter { name: BnString::new(raw_name).into_raw(), - type_: parameter.t.contents.handle, + type_: parameter.t.contents.as_raw(), typeConfidence: parameter.t.confidence, defaultLocation: parameter.location.is_none(), location, diff --git a/rust/src/debuginfo.rs b/rust/src/debuginfo.rs index f29f8ac23..c0232a1fa 100644 --- a/rust/src/debuginfo.rs +++ b/rust/src/debuginfo.rs @@ -297,7 +297,7 @@ pub struct DebugFunctionInfo { short_name: Option, full_name: Option, raw_name: Option, - type_: Option>, + type_: Option, address: u64, platform: Option>, components: Vec, @@ -317,7 +317,7 @@ impl From<&BNDebugFunctionInfo> for DebugFunctionInfo { type_: if raw.type_.is_null() { None } else { - Some(unsafe { Type::ref_from_raw(raw.type_) }) + Some(unsafe { Type::from_raw(ptr::NonNull::new(raw.type_).unwrap()) }) }, address: raw.address, platform: if raw.platform.is_null() { @@ -335,7 +335,7 @@ impl DebugFunctionInfo { short_name: Option, full_name: Option, raw_name: Option, - type_: Option>, + type_: Option, address: Option, platform: Option>, components: Vec, @@ -422,10 +422,7 @@ impl DebugInfo { } /// Returns a generator of all functions provided by a named DebugInfoParser - pub fn functions_by_name( - &self, - parser_name: S - ) -> Vec { + pub fn functions_by_name(&self, parser_name: S) -> Vec { let parser_name = parser_name.into_bytes_with_nul(); let mut count: usize = 0; @@ -510,7 +507,7 @@ impl DebugInfo { } /// May return nullptr - pub fn type_by_name(&self, parser_name: S, name: S) -> Option> { + pub fn type_by_name(&self, parser_name: S, name: S) -> Option { let parser_name = parser_name.into_bytes_with_nul(); let name = name.into_bytes_with_nul(); @@ -522,7 +519,7 @@ impl DebugInfo { ) }; if !result.is_null() { - Some(unsafe { Type::ref_from_raw(result) }) + Some(unsafe { Type::from_raw(ptr::NonNull::new(result).unwrap()) }) } else { None } @@ -532,7 +529,7 @@ impl DebugInfo { &self, parser_name: S, name: S, - ) -> Option<(u64, Ref)> { + ) -> Option<(u64, Type)> { let parser_name = parser_name.into_bytes_with_nul(); let name = name.into_bytes_with_nul(); @@ -545,8 +542,16 @@ impl DebugInfo { }; if !result.is_null() { - unsafe { BNFreeString((*result).name) }; - Some(unsafe { ((*result).address, Type::ref_from_raw((*result).type_)) }) + let BNDataVariableAndName { + address, + type_, + name, + autoDiscovered: _, + typeConfidence: _, + } = unsafe { *result }; + unsafe { BNFreeString(name) }; + let var_type = unsafe { Type::from_raw(ptr::NonNull::new(type_).unwrap()) }; + Some((address, var_type)) } else { None } @@ -556,7 +561,7 @@ impl DebugInfo { &self, parser_name: S, address: u64, - ) -> Option<(String, Ref)> { + ) -> Option<(String, Type)> { let parser_name = parser_name.into_bytes_with_nul(); let name_and_var = unsafe { BNGetDebugDataVariableByAddress( @@ -567,13 +572,20 @@ impl DebugInfo { }; if !name_and_var.is_null() { + let BNDataVariableAndName { + address: _, + type_, + name, + autoDiscovered: _, + typeConfidence: _, + } = unsafe { *name_and_var }; let result = unsafe { ( - raw_to_string((*name_and_var).name).unwrap(), - Type::ref_from_raw((*name_and_var).type_), + raw_to_string(name).unwrap(), + Type::from_raw(ptr::NonNull::new(type_).unwrap()), ) }; - unsafe { BNFreeString((*name_and_var).name) }; + unsafe { BNFreeString(name) }; Some(result) } else { None @@ -581,7 +593,7 @@ impl DebugInfo { } // The tuple is (DebugInfoParserName, type) - pub fn get_types_by_name(&self, name: S) -> Vec<(String, Ref)> { + pub fn get_types_by_name(&self, name: S) -> Vec<(String, Type)> { let name = name.into_bytes_with_nul(); let mut count: usize = 0; @@ -596,9 +608,15 @@ impl DebugInfo { .iter() .take(count) .map(|&name_and_type| unsafe { + assert!(!name_and_type.is_null()); + let BNNameAndType { + name, + type_, + typeConfidence: _, + } = *name_and_type; ( - raw_to_string((*name_and_type).name).unwrap(), - Type::ref_from_raw(BNNewTypeReference((*name_and_type).type_)), + raw_to_string(name).unwrap(), + Type::from_raw(ptr::NonNull::new(BNNewTypeReference(type_)).unwrap()), ) }) .collect(); @@ -611,7 +629,7 @@ impl DebugInfo { pub fn get_data_variables_by_name( &self, name: S, - ) -> Vec<(String, u64, Ref)> { + ) -> Vec<(String, u64, Type)> { let name = name.into_bytes_with_nul(); let mut count: usize = 0; @@ -626,10 +644,18 @@ impl DebugInfo { .iter() .take(count) .map(|&variable_and_name| unsafe { + assert!(!variable_and_name.is_null()); + let BNDataVariableAndName { + address, + type_, + name, + autoDiscovered: _, + typeConfidence: _, + } = *variable_and_name; ( - raw_to_string((*variable_and_name).name).unwrap(), - (*variable_and_name).address, - Type::ref_from_raw(BNNewTypeReference((*variable_and_name).type_)), + raw_to_string(name).unwrap(), + address, + Type::from_raw(ptr::NonNull::new(BNNewTypeReference(type_)).unwrap()), ) }) .collect(); @@ -639,7 +665,7 @@ impl DebugInfo { } /// The tuple is (DebugInfoParserName, TypeName, type) - pub fn get_data_variables_by_address(&self, address: u64) -> Vec<(String, String, Ref)> { + pub fn get_data_variables_by_address(&self, address: u64) -> Vec<(String, String, Type)> { let mut count: usize = 0; let raw_variables_and_names = unsafe { BNGetDebugDataVariablesByAddress(self.handle, address, &mut count) }; @@ -651,10 +677,19 @@ impl DebugInfo { .iter() .take(count) .map(|&variable_and_name| unsafe { + assert!(!variable_and_name.is_null()); + let BNDataVariableAndNameAndDebugParser { + address: _, + type_, + name, + parser, + autoDiscovered: _, + typeConfidence: _, + } = *variable_and_name; ( - raw_to_string((*variable_and_name).parser).unwrap(), - raw_to_string((*variable_and_name).name).unwrap(), - Type::ref_from_raw(BNNewTypeReference((*variable_and_name).type_)), + raw_to_string(parser).unwrap(), + raw_to_string(name).unwrap(), + Type::from_raw(ptr::NonNull::new(BNNewTypeReference(type_)).unwrap()), ) }) .collect(); @@ -754,7 +789,7 @@ impl DebugInfo { BNAddDebugType( self.handle, name.as_ref().as_ptr() as *mut _, - new_type.handle, + new_type.as_raw(), components_array.as_ptr() as _, components.len(), ) @@ -791,7 +826,7 @@ impl DebugInfo { rawName: raw_name, address: new_func.address, type_: match new_func.type_ { - Some(type_) => type_.handle, + Some(type_) => type_.as_raw(), _ => ptr::null_mut(), }, platform: match new_func.platform { @@ -826,7 +861,7 @@ impl DebugInfo { BNAddDebugDataVariable( self.handle, address, - t.handle, + t.as_raw(), name.as_ref().as_ptr() as *mut _, components.as_ptr() as _, components.len(), @@ -837,7 +872,7 @@ impl DebugInfo { BNAddDebugDataVariable( self.handle, address, - t.handle, + t.as_raw(), ptr::null_mut(), components.as_ptr() as _, components.len(), @@ -853,7 +888,7 @@ impl DebugInfo { self.handle, &BNDataVariableAndName { address: var.address, - type_: var.t.contents.handle, + type_: var.t.contents.as_raw(), name: name.as_ref().as_ptr() as *mut _, autoDiscovered: var.auto_discovered, typeConfidence: var.t.confidence, diff --git a/rust/src/demangle.rs b/rust/src/demangle.rs index 1b940ff91..d9c7a2446 100644 --- a/rust/src/demangle.rs +++ b/rust/src/demangle.rs @@ -16,6 +16,7 @@ use binaryninjacore_sys::*; use std::os::raw::c_char; +use std::ptr::NonNull; use std::{ffi::CStr, result}; use crate::architecture::CoreArchitecture; @@ -73,7 +74,7 @@ pub fn demangle_gnu3( arch: &CoreArchitecture, mangled_name: S, simplify: bool, -) -> Result<(Option>, Vec)> { +) -> Result<(Option, Vec)> { let mangled_name_bwn = mangled_name.into_bytes_with_nul(); let mangled_name_ptr = mangled_name_bwn.as_ref(); let mut out_type: *mut BNType = std::ptr::null_mut(); @@ -106,7 +107,7 @@ pub fn demangle_gnu3( log::debug!("demangle_gnu3: out_type is NULL"); None } - false => Some(unsafe { Type::ref_from_raw(out_type) }), + false => Some(unsafe { Type::from_raw(NonNull::new(out_type).unwrap()) }), }; if out_name.is_null() { @@ -128,7 +129,7 @@ pub fn demangle_ms( arch: &CoreArchitecture, mangled_name: S, simplify: bool, -) -> Result<(Option>, Vec)> { +) -> Result<(Option, Vec)> { let mangled_name_bwn = mangled_name.into_bytes_with_nul(); let mangled_name_ptr = mangled_name_bwn.as_ref(); @@ -162,7 +163,7 @@ pub fn demangle_ms( log::debug!("demangle_ms: out_type is NULL"); None } - false => Some(unsafe { Type::ref_from_raw(out_type) }), + false => Some(unsafe { Type::from_raw(NonNull::new(out_type).unwrap()) }), }; if out_name.is_null() { diff --git a/rust/src/function.rs b/rust/src/function.rs index 48f02205b..dce724417 100644 --- a/rust/src/function.rs +++ b/rust/src/function.rs @@ -39,8 +39,8 @@ pub use binaryninjacore_sys::BNAnalysisSkipReason as AnalysisSkipReason; pub use binaryninjacore_sys::BNFunctionAnalysisSkipOverride as FunctionAnalysisSkipOverride; pub use binaryninjacore_sys::BNFunctionUpdateType as FunctionUpdateType; -use std::{fmt, mem}; use std::{ffi::c_char, hash::Hash, ops::Range}; +use std::{fmt, mem, ptr::NonNull}; pub struct Location { pub arch: Option, @@ -372,11 +372,11 @@ impl Function { (!llil.is_null()).then(|| unsafe { llil::LiftedFunction::from_raw(self.arch(), llil) }) } - pub fn return_type(&self) -> Conf> { + pub fn return_type(&self) -> Conf { let result = unsafe { BNGetFunctionReturnType(self.handle) }; Conf::new( - unsafe { Type::ref_from_raw(result.type_) }, + unsafe { Type::from_raw(NonNull::new(result.type_).unwrap()) }, result.confidence, ) } @@ -390,7 +390,7 @@ impl Function { BNSetAutoFunctionReturnType( self.handle, &mut BNTypeWithConfidence { - type_: return_type.contents.handle, + type_: return_type.contents.as_raw(), confidence: return_type.confidence, }, ) @@ -406,15 +406,15 @@ impl Function { BNSetUserFunctionReturnType( self.handle, &mut BNTypeWithConfidence { - type_: return_type.contents.handle, + type_: return_type.contents.as_raw(), confidence: return_type.confidence, }, ) } } - pub fn function_type(&self) -> Ref { - unsafe { Type::ref_from_raw(BNGetFunctionType(self.handle)) } + pub fn function_type(&self) -> Type { + unsafe { Type::from_raw(NonNull::new(BNGetFunctionType(self.handle)).unwrap()) } } pub fn has_user_type(&self) -> bool { @@ -422,11 +422,11 @@ impl Function { } pub fn set_user_type(&self, t: &Type) { - unsafe { BNSetFunctionUserType(self.handle, t.handle) } + unsafe { BNSetFunctionUserType(self.handle, t.as_raw()) } } pub fn set_auto_type(&self, t: &Type) { - unsafe { BNSetFunctionAutoType(self.handle, t.handle) } + unsafe { BNSetFunctionAutoType(self.handle, t.as_raw()) } } pub fn stack_layout(&self) -> Array { @@ -514,11 +514,15 @@ impl Function { &self, addr: u64, arch: Option, - ) -> Option>> { + ) -> Option> { let arch = arch.unwrap_or_else(|| self.arch()); let result = unsafe { BNGetCallTypeAdjustment(self.handle, arch.0, addr) }; - (!result.type_.is_null()) - .then(|| unsafe { Conf::new(Type::ref_from_raw(result.type_), result.confidence) }) + (!result.type_.is_null()).then(|| unsafe { + Conf::new( + Type::from_raw(NonNull::new(result.type_).unwrap()), + result.confidence, + ) + }) } /// Sets or removes the call type override at a call site to the given type. @@ -538,7 +542,7 @@ impl Function { let mut adjust_type = adjust_type.map(|adjust_type| { let adjust_type = adjust_type.into(); BNTypeWithConfidence { - type_: adjust_type.contents.handle, + type_: adjust_type.contents.as_raw(), confidence: adjust_type.confidence, } }); @@ -565,7 +569,7 @@ impl Function { arch.0, addr, &mut BNTypeWithConfidence { - type_: adjust_type.contents.handle, + type_: adjust_type.contents.as_raw(), confidence: adjust_type.confidence, }, ) @@ -806,7 +810,9 @@ impl Function { arch: Option, ) -> RegisterValue { let arch = arch.unwrap_or_else(|| self.arch()); - let func_type = func_type.map(|f| f.handle).unwrap_or(core::ptr::null_mut()); + let func_type = func_type + .map(|f| f.as_raw() as *mut BNType) + .unwrap_or(core::ptr::null_mut()); let value = unsafe { BNGetParameterValueAtInstruction(self.handle, arch.0, addr, func_type, i) }; value.into() @@ -819,7 +825,7 @@ impl Function { i: usize, ) -> RegisterValue { let value = unsafe { - BNGetParameterValueAtLowLevelILInstruction(self.handle, instr, func_type.handle, i) + BNGetParameterValueAtLowLevelILInstruction(self.handle, instr, func_type.as_raw(), i) }; value.into() } @@ -830,7 +836,7 @@ impl Function { self.handle, sym.handle, if let Some(t) = t { - t.handle + t.as_raw() } else { core::ptr::null_mut() }, @@ -839,7 +845,7 @@ impl Function { } pub fn apply_auto_discovered_type(&self, func_type: &Type) { - unsafe { BNApplyAutoDiscoveredFunctionType(self.handle, func_type.handle) } + unsafe { BNApplyAutoDiscoveredFunctionType(self.handle, func_type.as_raw()) } } /// Whether automatic analysis was skipped for this function. @@ -1705,7 +1711,7 @@ impl Function { addr: u64, offset: i64, arch: Option, - ) -> Option<(Variable, BnString, Conf>)> { + ) -> Option<(Variable, BnString, Conf)> { let arch = arch.unwrap_or_else(|| self.arch()); let mut found_value: BNVariableNameAndType = unsafe { mem::zeroed() }; let found = unsafe { @@ -1717,7 +1723,7 @@ impl Function { let var = unsafe { Variable::from_raw(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_) }, + unsafe { Type::from_raw(NonNull::new(found_value.type_).unwrap()) }, found_value.typeConfidence, ); Some((var, name, var_type)) diff --git a/rust/src/mlil/instruction.rs b/rust/src/mlil/instruction.rs index 88564cc61..c9f102b48 100644 --- a/rust/src/mlil/instruction.rs +++ b/rust/src/mlil/instruction.rs @@ -1,3 +1,5 @@ +use std::ptr::NonNull; + use binaryninjacore_sys::*; use crate::architecture::CoreIntrinsic; @@ -1138,11 +1140,11 @@ impl MediumLevelILInstruction { } /// Type of expression - pub fn expr_type(&self) -> Option>> { + pub fn expr_type(&self) -> Option> { let result = unsafe { BNGetMediumLevelILExprType(self.function.handle, self.index) }; (!result.type_.is_null()).then(|| { Conf::new( - unsafe { Type::ref_from_raw(result.type_) }, + unsafe { Type::from_raw(NonNull::new(result.type_).unwrap()) }, result.confidence, ) }) @@ -1157,7 +1159,7 @@ impl MediumLevelILInstruction { pub fn set_expr_type<'a, T: Into>>(&self, value: T) { let type_: Conf<&'a Type> = value.into(); let mut type_raw: BNTypeWithConfidence = BNTypeWithConfidence { - type_: type_.contents.handle, + type_: type_.contents.as_raw(), confidence: type_.confidence, }; unsafe { BNSetMediumLevelILExprType(self.function.handle, self.index, &mut type_raw) } diff --git a/rust/src/platform.rs b/rust/src/platform.rs index 11f76284b..2af76916c 100644 --- a/rust/src/platform.rs +++ b/rust/src/platform.rs @@ -14,17 +14,19 @@ //! Contains all information related to the execution environment of the binary, mainly the calling conventions used -use std::{borrow::Borrow, collections::HashMap, os::raw, path::Path, ptr, slice}; +use std::borrow::Borrow; +use std::collections::HashMap; +use std::os::raw; +use std::path::Path; +use std::{ptr, slice}; use binaryninjacore_sys::*; -use crate::{ - architecture::{Architecture, CoreArchitecture}, - callingconvention::CallingConvention, - rc::*, - string::*, - types::{QualifiedName, QualifiedNameAndType, Type}, -}; +use crate::architecture::{Architecture, CoreArchitecture}; +use crate::callingconvention::CallingConvention; +use crate::rc::*; +use crate::string::*; +use crate::types::{QualifiedName, QualifiedNameAndType, Type}; #[derive(PartialEq, Eq, Hash)] pub struct Platform { @@ -257,9 +259,9 @@ pub trait TypeParser { #[derive(Clone, Default)] pub struct TypeParserResult { - pub types: HashMap>, - pub variables: HashMap>, - pub functions: HashMap>, + pub types: HashMap, + pub variables: HashMap, + pub functions: HashMap, } impl TypeParser for Platform { @@ -318,23 +320,26 @@ impl TypeParser for Platform { for i in slice::from_raw_parts(result.types, result.typeCount) { let name = QualifiedName(i.name); - type_parser_result - .types - .insert(name.string(), Type::ref_from_raw(i.type_)); + type_parser_result.types.insert( + name.string(), + Type::from_raw(ptr::NonNull::new(i.type_).unwrap()), + ); } for i in slice::from_raw_parts(result.functions, result.functionCount) { let name = QualifiedName(i.name); - type_parser_result - .functions - .insert(name.string(), Type::ref_from_raw(i.type_)); + type_parser_result.functions.insert( + name.string(), + Type::from_raw(ptr::NonNull::new(i.type_).unwrap()), + ); } for i in slice::from_raw_parts(result.variables, result.variableCount) { let name = QualifiedName(i.name); - type_parser_result - .variables - .insert(name.string(), Type::ref_from_raw(i.type_)); + type_parser_result.variables.insert( + name.string(), + Type::from_raw(ptr::NonNull::new(i.type_).unwrap()), + ); } } diff --git a/rust/src/types.rs b/rust/src/types.rs index 9835690e1..ca36ea4f1 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -87,11 +87,12 @@ impl Conf { Conf::new(f(self.contents), self.confidence) } - pub fn as_ref(&self) -> Conf<&U> - where - T: AsRef, - { - Conf::new(self.contents.as_ref(), self.confidence) + pub fn as_ref(&self) -> Conf<&T> { + let Conf { + ref contents, + confidence, + } = *self; + Conf::new(contents, confidence) } } @@ -226,10 +227,10 @@ impl From for Conf { } } -impl From for Conf> { +impl From for Conf { fn from(type_with_confidence: BNTypeWithConfidence) -> Self { Self::new( - unsafe { Type::ref_from_raw(type_with_confidence.type_) }, + unsafe { Type::from_raw(NonNull::new(type_with_confidence.type_).unwrap()) }, type_with_confidence.confidence, ) } @@ -269,7 +270,7 @@ impl From for Conf { impl From> for BNTypeWithConfidence { fn from(conf: Conf<&Type>) -> Self { Self { - type_: conf.contents.handle, + type_: conf.contents.as_raw(), confidence: conf.confidence, } } @@ -313,7 +314,7 @@ pub struct TypeBuilder { impl TypeBuilder { pub fn new(t: &Type) -> Self { - unsafe { Self::from_raw(NonNull::new(BNCreateTypeBuilderFromType(t.handle)).unwrap()) } + unsafe { Self::from_raw(NonNull::new(BNCreateTypeBuilderFromType(t.as_raw())).unwrap()) } } pub(crate) unsafe fn from_raw(handle: NonNull) -> Self { @@ -325,8 +326,8 @@ impl TypeBuilder { } // Chainable terminal - pub fn finalize(&self) -> Ref { - unsafe { Type::ref_from_raw(BNFinalizeTypeBuilder(self.as_raw())) } + pub fn finalize(&self) -> Type { + unsafe { Type::from_raw(NonNull::new(BNFinalizeTypeBuilder(self.as_raw())).unwrap()) } } // Settable properties @@ -385,7 +386,7 @@ impl TypeBuilder { unsafe { BNIsTypeBuilderFloatingPoint(self.as_raw()) } } - pub fn target(&self) -> Result>> { + pub fn target(&self) -> Result> { let raw_target = unsafe { BNGetTypeBuilderChildType(self.as_raw()) }; if raw_target.type_.is_null() { Err(()) @@ -394,7 +395,7 @@ impl TypeBuilder { } } - pub fn element_type(&self) -> Result>> { + pub fn element_type(&self) -> Result> { let raw_target = unsafe { BNGetTypeBuilderChildType(self.as_raw()) }; if raw_target.type_.is_null() { Err(()) @@ -403,7 +404,7 @@ impl TypeBuilder { } } - pub fn return_value(&self) -> Result>> { + pub fn return_value(&self) -> Result> { let raw_target = unsafe { BNGetTypeBuilderChildType(self.as_raw()) }; if raw_target.type_.is_null() { Err(()) @@ -606,7 +607,7 @@ impl TypeBuilder { let result = BNCreateNamedTypeReferenceBuilderFromTypeAndId( BnString::new("").as_ptr() as *mut _, &mut name.0, - t.handle, + t.as_raw(), ); Self::from_raw(NonNull::new(result).unwrap()) } @@ -709,7 +710,7 @@ impl Drop for TypeBuilder { #[repr(transparent)] pub struct Type { - pub(crate) handle: *mut BNType, + handle: NonNull, } /// ```no_run @@ -722,14 +723,21 @@ pub struct Type { /// bv.define_user_type("int_2", &my_custom_type_2); /// ``` impl Type { - unsafe fn from_raw(handle: *mut BNType) -> Self { - debug_assert!(!handle.is_null()); + pub(crate) unsafe fn from_raw(handle: NonNull) -> Self { Self { handle } } - pub(crate) unsafe fn ref_from_raw(handle: *mut BNType) -> Ref { - debug_assert!(!handle.is_null()); - Ref::new(Self { handle }) + pub(crate) unsafe fn ref_from_raw(handle: &*mut BNType) -> &Self { + assert!(!handle.is_null()); + mem::transmute(handle) + } + + pub(crate) fn as_raw(&self) -> &mut BNType { + unsafe { &mut (*self.handle.as_ptr()) } + } + + pub(crate) fn into_raw(self) -> *mut BNType { + ManuallyDrop::new(self).handle.as_ptr() } pub fn to_builder(&self) -> TypeBuilder { @@ -739,35 +747,35 @@ impl Type { // Readable properties pub fn type_class(&self) -> TypeClass { - unsafe { BNGetTypeClass(self.handle) } + unsafe { BNGetTypeClass(self.as_raw()) } } pub fn width(&self) -> u64 { - unsafe { BNGetTypeWidth(self.handle) } + unsafe { BNGetTypeWidth(self.as_raw()) } } pub fn alignment(&self) -> usize { - unsafe { BNGetTypeAlignment(self.handle) } + unsafe { BNGetTypeAlignment(self.as_raw()) } } pub fn is_signed(&self) -> Conf { - unsafe { BNIsTypeSigned(self.handle).into() } + unsafe { BNIsTypeSigned(self.as_raw()).into() } } pub fn is_const(&self) -> Conf { - unsafe { BNIsTypeConst(self.handle).into() } + unsafe { BNIsTypeConst(self.as_raw()).into() } } pub fn is_volatile(&self) -> Conf { - unsafe { BNIsTypeVolatile(self.handle).into() } + unsafe { BNIsTypeVolatile(self.as_raw()).into() } } pub fn is_floating_point(&self) -> bool { - unsafe { BNIsTypeFloatingPoint(self.handle) } + unsafe { BNIsTypeFloatingPoint(self.as_raw()) } } - pub fn target(&self) -> Result>> { - let raw_target = unsafe { BNGetChildType(self.handle) }; + pub fn target(&self) -> Result> { + let raw_target = unsafe { BNGetChildType(self.as_raw()) }; if raw_target.type_.is_null() { Err(()) } else { @@ -775,8 +783,8 @@ impl Type { } } - pub fn element_type(&self) -> Result>> { - let raw_target = unsafe { BNGetChildType(self.handle) }; + pub fn element_type(&self) -> Result> { + let raw_target = unsafe { BNGetChildType(self.as_raw()) }; if raw_target.type_.is_null() { Err(()) } else { @@ -784,8 +792,8 @@ impl Type { } } - pub fn return_value(&self) -> Result>> { - let raw_target = unsafe { BNGetChildType(self.handle) }; + pub fn return_value(&self) -> Result> { + let raw_target = unsafe { BNGetChildType(self.as_raw()) }; if raw_target.type_.is_null() { Err(()) } else { @@ -794,7 +802,7 @@ impl Type { } pub fn calling_convention(&self) -> Result>>> { - let convention_confidence = unsafe { BNGetTypeCallingConvention(self.handle) }; + let convention_confidence = unsafe { BNGetTypeCallingConvention(self.as_raw()) }; if convention_confidence.convention.is_null() { Err(()) } else { @@ -806,7 +814,7 @@ impl Type { unsafe { let mut count = 0; let parameters_raw: *mut BNFunctionParameter = - BNGetTypeParameters(self.handle, &mut count); + BNGetTypeParameters(self.as_raw(), &mut count); if parameters_raw.is_null() { Err(()) } else { @@ -825,19 +833,19 @@ impl Type { } pub fn has_variable_arguments(&self) -> Conf { - unsafe { BNTypeHasVariableArguments(self.handle).into() } + unsafe { BNTypeHasVariableArguments(self.as_raw()).into() } } pub fn can_return(&self) -> Conf { - unsafe { BNFunctionTypeCanReturn(self.handle).into() } + unsafe { BNFunctionTypeCanReturn(self.as_raw()).into() } } pub fn pure(&self) -> Conf { - unsafe { BNIsTypePure(self.handle).into() } + unsafe { BNIsTypePure(self.as_raw()).into() } } pub fn get_structure(&self) -> Result> { - let result = unsafe { BNGetTypeStructure(self.handle) }; + let result = unsafe { BNGetTypeStructure(self.as_raw()) }; if result.is_null() { Err(()) } else { @@ -846,7 +854,7 @@ impl Type { } pub fn get_enumeration(&self) -> Result> { - let result = unsafe { BNGetTypeEnumeration(self.handle) }; + let result = unsafe { BNGetTypeEnumeration(self.as_raw()) }; if result.is_null() { Err(()) } else { @@ -855,7 +863,7 @@ impl Type { } pub fn get_named_type_reference(&self) -> Result> { - let result = unsafe { BNGetTypeNamedTypeReference(self.handle) }; + let result = unsafe { BNGetTypeNamedTypeReference(self.as_raw()) }; if result.is_null() { Err(()) } else { @@ -864,19 +872,19 @@ impl Type { } pub fn count(&self) -> u64 { - unsafe { BNGetTypeElementCount(self.handle) } + unsafe { BNGetTypeElementCount(self.as_raw()) } } pub fn offset(&self) -> u64 { - unsafe { BNGetTypeOffset(self.handle) } + unsafe { BNGetTypeOffset(self.as_raw()) } } pub fn stack_adjustment(&self) -> Conf { - unsafe { BNGetTypeStackAdjustment(self.handle).into() } + unsafe { BNGetTypeStackAdjustment(self.as_raw()).into() } } pub fn registered_name(&self) -> Result> { - let result = unsafe { BNGetRegisteredTypeName(self.handle) }; + let result = unsafe { BNGetRegisteredTypeName(self.as_raw()) }; if result.is_null() { Err(()) } else { @@ -887,70 +895,66 @@ impl Type { // TODO : This and properties // pub fn tokens(&self) -> ? {} - pub fn void() -> Ref { - unsafe { Self::ref_from_raw(BNCreateVoidType()) } + pub fn void() -> Self { + unsafe { Self::from_raw(NonNull::new(BNCreateVoidType()).unwrap()) } } - pub fn bool() -> Ref { - unsafe { Self::ref_from_raw(BNCreateBoolType()) } + pub fn bool() -> Self { + unsafe { Self::from_raw(NonNull::new(BNCreateBoolType()).unwrap()) } } - pub fn char() -> Ref { + pub fn char() -> Self { Self::int(1, true) } - pub fn wide_char(width: usize) -> Ref { + pub fn wide_char(width: usize) -> Self { unsafe { - Self::ref_from_raw(BNCreateWideCharType( - width, - BnString::new("").as_ptr() as *mut _, - )) + let result = BNCreateWideCharType(width, BnString::new("").as_ptr() as *mut _); + Self::from_raw(NonNull::new(result).unwrap()) } } - pub fn int(width: usize, is_signed: bool) -> Ref { + pub fn int(width: usize, is_signed: bool) -> Self { let mut is_signed = Conf::new(is_signed, max_confidence()).into(); unsafe { - Self::ref_from_raw(BNCreateIntegerType( - width, - &mut is_signed, - BnString::new("").as_ptr() as *mut _, - )) + let result = + BNCreateIntegerType(width, &mut is_signed, BnString::new("").as_ptr() as *mut _); + Self::from_raw(NonNull::new(result).unwrap()) } } - pub fn named_int(width: usize, is_signed: bool, alt_name: S) -> Ref { + pub fn named_int(width: usize, is_signed: bool, alt_name: S) -> Self { let mut is_signed = Conf::new(is_signed, max_confidence()).into(); // let alt_name = BnString::new(alt_name); let alt_name = alt_name.into_bytes_with_nul(); // This segfaulted once, so the above version is there if we need to change to it, but in theory this is copied into a `const string&` on the C++ side; I'm just not 100% confident that a constant reference copies data unsafe { - Self::ref_from_raw(BNCreateIntegerType( - width, - &mut is_signed, - alt_name.as_ref().as_ptr() as _, - )) + let result = + BNCreateIntegerType(width, &mut is_signed, alt_name.as_ref().as_ptr() as _); + Self::from_raw(NonNull::new(result).unwrap()) } } - pub fn float(width: usize) -> Ref { + pub fn float(width: usize) -> Self { unsafe { - Self::ref_from_raw(BNCreateFloatType( - width, - BnString::new("").as_ptr() as *mut _, - )) + let result = BNCreateFloatType(width, BnString::new("").as_ptr() as *mut _); + Self::from_raw(NonNull::new(result).unwrap()) } } - pub fn named_float(width: usize, alt_name: S) -> Ref { + pub fn named_float(width: usize, alt_name: S) -> Self { // let alt_name = BnString::new(alt_name); let alt_name = alt_name.into_bytes_with_nul(); // See same line in `named_int` above - unsafe { Self::ref_from_raw(BNCreateFloatType(width, alt_name.as_ref().as_ptr() as _)) } + unsafe { + Self::from_raw( + NonNull::new(BNCreateFloatType(width, alt_name.as_ref().as_ptr() as _)).unwrap(), + ) + } } - pub fn array<'a, T: Into>>(t: T, count: u64) -> Ref { - unsafe { Self::ref_from_raw(BNCreateArrayType(&t.into().into(), count)) } + pub fn array<'a, T: Into>>(t: T, count: u64) -> Self { + unsafe { Self::from_raw(NonNull::new(BNCreateArrayType(&t.into().into(), count)).unwrap()) } } /// The C/C++ APIs require an associated architecture, but in the core we only query the default_int_size if the given width is 0 @@ -960,46 +964,49 @@ impl Type { enumeration: &Enumeration, width: usize, is_signed: T, - ) -> Ref { + ) -> Self { unsafe { // TODO : This is _extremely fragile_, we should change the internals of BNCreateEnumerationType instead of doing this let mut fake_arch: BNArchitecture = mem::zeroed(); - Self::ref_from_raw(BNCreateEnumerationType( + let result = BNCreateEnumerationType( &mut fake_arch, enumeration.handle, width, &mut is_signed.into().into(), - )) + ); + Self::from_raw(NonNull::new(result).unwrap()) } } - pub fn structure(structure: &Structure) -> Ref { - unsafe { Self::ref_from_raw(BNCreateStructureType(structure.handle)) } + pub fn structure(structure: &Structure) -> Self { + unsafe { Self::from_raw(NonNull::new(BNCreateStructureType(structure.handle)).unwrap()) } } - pub fn named_type(type_reference: &NamedTypeReference) -> Ref { + pub fn named_type(type_reference: &NamedTypeReference) -> Self { let mut is_const = Conf::new(false, min_confidence()).into(); let mut is_volatile = Conf::new(false, min_confidence()).into(); unsafe { - Self::ref_from_raw(BNCreateNamedTypeReference( + let result = BNCreateNamedTypeReference( type_reference.handle, 0, 1, &mut is_const, &mut is_volatile, - )) + ); + Self::from_raw(NonNull::new(result).unwrap()) } } - pub fn named_type_from_type(name: S, t: &Type) -> Ref { + pub fn named_type_from_type(name: S, t: &Type) -> Self { let mut name = QualifiedName::from(name); unsafe { - Self::ref_from_raw(BNCreateNamedTypeReferenceFromTypeAndId( + let result = BNCreateNamedTypeReferenceFromTypeAndId( BnString::new("").as_ptr() as *mut _, &mut name.0, - t.handle, - )) + t.as_raw(), + ); + Self::from_raw(NonNull::new(result).unwrap()) } } @@ -1007,7 +1014,7 @@ impl Type { return_type: T, parameters: &[FunctionParameter], variable_arguments: bool, - ) -> Ref { + ) -> Self { let mut return_type = return_type.into().into(); let mut variable_arguments = Conf::new(variable_arguments, max_confidence()).into(); let mut can_return = Conf::new(true, min_confidence()).into(); @@ -1031,7 +1038,7 @@ impl Type { raw_parameters.push(BNFunctionParameter { name: raw_name.as_slice().as_ptr() as *mut _, - type_: parameter.t.contents.handle, + type_: parameter.t.contents.as_raw(), typeConfidence: parameter.t.confidence, defaultLocation: parameter.location.is_none(), location, @@ -1048,7 +1055,7 @@ impl Type { }; unsafe { - Self::ref_from_raw(BNNewTypeReference(BNCreateFunctionType( + let result = BNNewTypeReference(BNCreateFunctionType( &mut return_type, &mut raw_calling_convention, raw_parameters.as_mut_ptr(), @@ -1062,7 +1069,8 @@ impl Type { &mut return_regs, BNNameType::NoNameType, &mut pure, - ))) + )); + Self::from_raw(NonNull::new(result).unwrap()) } } @@ -1077,7 +1085,7 @@ impl Type { variable_arguments: bool, calling_convention: C, stack_adjust: Conf, - ) -> Ref { + ) -> Self { let mut return_type = return_type.into().into(); let mut variable_arguments = Conf::new(variable_arguments, max_confidence()).into(); let mut can_return = Conf::new(true, min_confidence()).into(); @@ -1102,7 +1110,7 @@ impl Type { raw_parameters.push(BNFunctionParameter { name: raw_name.as_slice().as_ptr() as *mut _, - type_: parameter.t.contents.handle, + type_: parameter.t.contents.as_raw(), typeConfidence: parameter.t.confidence, defaultLocation: parameter.location.is_none(), location, @@ -1121,7 +1129,7 @@ impl Type { }; unsafe { - Self::ref_from_raw(BNCreateFunctionType( + let result = BNCreateFunctionType( &mut return_type, &mut raw_calling_convention, raw_parameters.as_mut_ptr(), @@ -1135,38 +1143,38 @@ impl Type { &mut return_regs, BNNameType::NoNameType, &mut pure, - )) + ); + Self::from_raw(NonNull::new(result).unwrap()) } } - pub fn pointer<'a, A: Architecture, T: Into>>(arch: &A, t: T) -> Ref { + pub fn pointer<'a, A: Architecture, T: Into>>(arch: &A, t: T) -> Self { let mut is_const = Conf::new(false, min_confidence()).into(); let mut is_volatile = Conf::new(false, min_confidence()).into(); unsafe { - Self::ref_from_raw(BNCreatePointerType( + let result = BNCreatePointerType( arch.as_ref().0, &t.into().into(), &mut is_const, &mut is_volatile, ReferenceType::PointerReferenceType, - )) + ); + Self::from_raw(NonNull::new(result).unwrap()) } } - pub fn const_pointer<'a, A: Architecture, T: Into>>( - arch: &A, - t: T, - ) -> Ref { + pub fn const_pointer<'a, A: Architecture, T: Into>>(arch: &A, t: T) -> Self { let mut is_const = Conf::new(true, max_confidence()).into(); let mut is_volatile = Conf::new(false, min_confidence()).into(); unsafe { - Self::ref_from_raw(BNCreatePointerType( + let result = BNCreatePointerType( arch.as_ref().0, &t.into().into(), &mut is_const, &mut is_volatile, ReferenceType::PointerReferenceType, - )) + ); + Self::from_raw(NonNull::new(result).unwrap()) } } @@ -1176,17 +1184,18 @@ impl Type { is_const: bool, is_volatile: bool, ref_type: Option, - ) -> Ref { + ) -> Self { let mut is_const = Conf::new(is_const, max_confidence()).into(); let mut is_volatile = Conf::new(is_volatile, max_confidence()).into(); unsafe { - Self::ref_from_raw(BNCreatePointerTypeOfWidth( + let result = BNCreatePointerTypeOfWidth( size, &t.into().into(), &mut is_const, &mut is_volatile, ref_type.unwrap_or(ReferenceType::PointerReferenceType), - )) + ); + Self::from_raw(NonNull::new(result).unwrap()) } } @@ -1196,17 +1205,18 @@ impl Type { is_const: bool, is_volatile: bool, ref_type: Option, - ) -> Ref { + ) -> Self { let mut is_const = Conf::new(is_const, max_confidence()).into(); let mut is_volatile = Conf::new(is_volatile, max_confidence()).into(); unsafe { - Self::ref_from_raw(BNCreatePointerType( + let result = BNCreatePointerType( arch.as_ref().0, &t.into().into(), &mut is_const, &mut is_volatile, ref_type.unwrap_or(ReferenceType::PointerReferenceType), - )) + ); + Self::from_raw(NonNull::new(result).unwrap()) } } @@ -1220,7 +1230,7 @@ impl fmt::Display for Type { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", unsafe { BnString::from_raw(BNGetTypeString( - self.handle, + self.as_raw(), ptr::null_mut(), BNTokenEscapingType::NoTokenEscapingType, )) @@ -1241,7 +1251,7 @@ impl fmt::Debug for Type { let container = unsafe { BNGetAnalysisTypeContainer(bv.handle) }; let lines: *mut BNTypeDefinitionLine = unsafe { BNGetTypeLines( - self.handle, + self.as_raw(), container, "\x00".as_ptr() as *const c_char, 64, @@ -1288,7 +1298,7 @@ impl fmt::Debug for Type { impl PartialEq for Type { fn eq(&self, other: &Self) -> bool { - unsafe { BNTypesEqual(self.handle, other.handle) } + unsafe { BNTypesEqual(self.as_raw(), other.as_raw()) } } } @@ -1303,21 +1313,15 @@ impl Hash for Type { unsafe impl Send for Type {} unsafe impl Sync for Type {} -unsafe impl RefCountable for Type { - unsafe fn inc_ref(handle: &Self) -> Ref { - Self::ref_from_raw(BNNewTypeReference(handle.handle)) - } - - unsafe fn dec_ref(handle: &Self) { - BNFreeType(handle.handle); +impl Clone for Type { + fn clone(&self) -> Self { + unsafe { Self::from_raw(NonNull::new(BNNewTypeReference(self.as_raw())).unwrap()) } } } -impl ToOwned for Type { - type Owned = Ref; - - fn to_owned(&self) -> Self::Owned { - unsafe { RefCountable::inc_ref(self) } +impl Drop for Type { + fn drop(&mut self) { + unsafe { BNFreeType(self.as_raw()) }; } } @@ -1326,13 +1330,13 @@ impl ToOwned for Type { #[derive(Clone, Debug)] pub struct FunctionParameter { - pub t: Conf>, + pub t: Conf, pub name: String, pub location: Option, } impl FunctionParameter { - pub fn new>>>(t: T, name: String, location: Option) -> Self { + pub fn new>>(t: T, name: String, location: Option) -> Self { Self { t: t.into(), name, @@ -1358,7 +1362,7 @@ impl FunctionParameter { Self { t: Conf::new( - unsafe { Type::ref_from_raw(BNNewTypeReference(member.type_)) }, + unsafe { Type::from_raw(NonNull::new(BNNewTypeReference(member.type_)).unwrap()) }, member.typeConfidence, ), name, @@ -1521,8 +1525,8 @@ impl NamedTypedVariable { self.type_confidence } - pub fn var_type(&self) -> Ref { - unsafe { Ref::new(Type::from_raw(self.ty)) } + pub fn var_type(&self) -> Type { + unsafe { Type::from_raw(NonNull::new(self.ty).unwrap()) } } } @@ -1856,7 +1860,7 @@ impl StructureBuilder { pub fn insert_member(&self, member: &StructureMember, overwrite_existing: bool) -> &Self { let ty = member.ty.clone(); self.insert( - ty.as_ref(), + &ty, member.name.clone(), member.offset, overwrite_existing, @@ -2078,7 +2082,7 @@ impl Structure { let members = slice::from_raw_parts(members_raw, count); let result = (0..count) - .map(|i| StructureMember::from_raw(members[i])) + .map(|i| StructureMember::ref_from_raw(members[i])) .collect(); BNFreeStructureMemberList(members_raw, count); @@ -2143,7 +2147,7 @@ impl ToOwned for Structure { #[derive(Debug, Clone)] pub struct StructureMember { - pub ty: Conf>, + pub ty: Conf, pub name: String, pub offset: u64, pub access: MemberAccess, @@ -2152,7 +2156,7 @@ pub struct StructureMember { impl StructureMember { pub fn new( - ty: Conf>, + ty: Conf, name: String, offset: u64, access: MemberAccess, @@ -2167,10 +2171,10 @@ impl StructureMember { } } - pub(crate) unsafe fn from_raw(handle: BNStructureMember) -> Self { + pub(crate) unsafe fn ref_from_raw(handle: BNStructureMember) -> Self { Self { ty: Conf::new( - RefCountable::inc_ref(&Type::from_raw(handle.type_)), + Type::ref_from_raw(&handle.type_).clone(), handle.typeConfidence, ), name: CStr::from_ptr(handle.name).to_string_lossy().to_string(), @@ -2192,7 +2196,7 @@ unsafe impl CoreArrayProviderInner for StructureMember { BNFreeStructureMemberList(raw, count) } unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> { - Guard::new(StructureMember::from_raw(*raw), &()) + Guard::new(StructureMember::ref_from_raw(*raw), &()) } } @@ -2315,7 +2319,7 @@ impl NamedTypeReference { unsafe { BNGetTypeReferenceClass(self.handle) } } - fn target_helper(&self, bv: &BinaryView, visited: &mut HashSet) -> Option> { + fn target_helper(&self, bv: &BinaryView, visited: &mut HashSet) -> Option { // TODO : This is a clippy bug (#10088, I think); remove after we upgrade past 2022-12-12 #[allow(clippy::manual_filter)] if let Some(t) = bv.get_type_by_id(self.id()) { @@ -2336,7 +2340,7 @@ impl NamedTypeReference { } } - pub fn target(&self, bv: &BinaryView) -> Option> { + pub fn target(&self, bv: &BinaryView) -> Option { //! Returns the type referenced by this named type reference self.target_helper(bv, &mut HashSet::new()) } @@ -2511,7 +2515,7 @@ impl QualifiedNameAndType { } pub fn type_object(&self) -> Guard { - unsafe { Guard::new(Type::from_raw(self.0.type_), self) } + unsafe { Guard::new(Type::from_raw(NonNull::new(self.0.type_).unwrap()), self) } } } @@ -2553,7 +2557,7 @@ impl QualifiedNameTypeAndId { } pub fn type_object(&self) -> Guard { - unsafe { Guard::new(Type::from_raw(self.0.type_), self) } + unsafe { Guard::new(Type::from_raw(NonNull::new(self.0.type_).unwrap()), self) } } } @@ -2591,11 +2595,11 @@ impl NameAndType { } impl NameAndType { - pub fn new(name: S, t: &Type, confidence: u8) -> Ref { + pub fn new(name: S, t: Type, confidence: u8) -> Ref { unsafe { Ref::new(Self(BNNameAndType { name: BNAllocString(name.into_bytes_with_nul().as_ref().as_ptr() as *mut _), - type_: Ref::into_raw(t.to_owned()).handle, + type_: t.into_raw(), typeConfidence: confidence, })) } @@ -2607,7 +2611,7 @@ impl NameAndType { } pub fn t(&self) -> &Type { - unsafe { mem::transmute::<_, &Type>(&self.0.type_) } + unsafe { Type::ref_from_raw(&self.0.type_) } } pub fn type_with_confidence(&self) -> Conf<&Type> { @@ -2627,7 +2631,7 @@ unsafe impl RefCountable for NameAndType { unsafe fn inc_ref(handle: &Self) -> Ref { Self::new( CStr::from_ptr(handle.0.name), - handle.t(), + handle.t().clone(), handle.0.typeConfidence, ) } @@ -2635,7 +2639,7 @@ unsafe impl RefCountable for NameAndType { unsafe fn dec_ref(handle: &Self) { unsafe { BNFreeString(handle.0.name); - RefCountable::dec_ref(handle.t()); + let _ = Type::from_raw(NonNull::new(handle.0.type_).unwrap()); } } } @@ -2705,7 +2709,7 @@ unsafe impl RefCountable for DataVariable { unsafe fn inc_ref(handle: &Self) -> Ref { unsafe { Ref::new(Self(BNDataVariable { - type_: Ref::into_raw(handle.t().to_owned()).handle, + type_: handle.t().clone().into_raw(), ..handle.0 })) } @@ -2735,7 +2739,7 @@ unsafe impl CoreArrayProviderInner for DataVariable { pub struct DataVariableAndName { pub address: u64, - pub t: Conf>, + pub t: Conf, pub auto_discovered: bool, pub name: S, } @@ -2744,7 +2748,10 @@ impl DataVariableAndName { pub(crate) fn from_raw(var: &BNDataVariableAndName) -> Self { Self { address: var.address, - t: Conf::new(unsafe { Type::ref_from_raw(var.type_) }, var.typeConfidence), + t: Conf::new( + unsafe { Type::from_raw(NonNull::new(var.type_).unwrap()) }, + var.typeConfidence, + ), auto_discovered: var.autoDiscovered, name: raw_to_string(var.name).unwrap(), } @@ -2752,7 +2759,7 @@ impl DataVariableAndName { } impl DataVariableAndName { - pub fn new(address: u64, t: Conf>, auto_discovered: bool, name: S) -> Self { + pub fn new(address: u64, t: Conf, auto_discovered: bool, name: S) -> Self { Self { address, t, @@ -2761,7 +2768,7 @@ impl DataVariableAndName { } } - pub fn type_with_confidence(&self) -> Conf> { + pub fn type_with_confidence(&self) -> Conf { Conf::new(self.t.contents.clone(), self.t.confidence) } } @@ -3554,7 +3561,7 @@ pub type IntegerDisplayType = binaryninjacore_sys::BNIntegerDisplayType; #[derive(Debug, Clone)] pub struct StackVariableReference { _source_operand: u32, - var_type: Conf>, + var_type: Conf, name: BnString, var: Variable, offset: i64, @@ -3564,7 +3571,7 @@ pub struct StackVariableReference { impl StackVariableReference { pub fn from_raw(value: BNStackVariableReference) -> Self { let var_type = Conf::new( - unsafe { Type::ref_from_raw(value.type_) }, + unsafe { Type::from_raw(NonNull::new(value.type_).unwrap()) }, value.typeConfidence, ); let name = unsafe { BnString::from_raw(value.name) }; @@ -3736,7 +3743,7 @@ unsafe impl CoreArrayProviderInner for UnresolvedIndirectBranches { #[cfg(test)] mod test { - use crate::types::{Conf, FunctionParameter, TypeClass}; + use crate::types::{FunctionParameter, TypeClass}; use super::{Type, TypeBuilder}; From 37b7cb91813ef248728ea50946d46fa69471d184 Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Wed, 29 May 2024 09:59:20 -0300 Subject: [PATCH 03/33] change `BnString` to the new standard --- rust/src/architecture.rs | 6 +++-- rust/src/backgroundtask.rs | 5 ++++- rust/src/binaryview.rs | 6 ++--- rust/src/callingconvention.rs | 12 +++++----- rust/src/custombinaryview.rs | 14 +++++++----- rust/src/debuginfo.rs | 9 ++++++-- rust/src/disassembly.rs | 5 ++--- rust/src/downloadprovider.rs | 4 ++-- rust/src/filemetadata.rs | 9 +++++--- rust/src/function.rs | 21 +++++++++-------- rust/src/hlil/operation.rs | 5 ++++- rust/src/interaction.rs | 9 ++++---- rust/src/lib.rs | 41 +++++++++++----------------------- rust/src/metadata.rs | 9 ++++---- rust/src/platform.rs | 5 +++-- rust/src/section.rs | 9 ++++---- rust/src/settings.rs | 24 +++++++++++--------- rust/src/string.rs | 30 ++++++++++++------------- rust/src/symbol.rs | 9 ++++---- rust/src/tags.rs | 12 +++++----- rust/src/templatesimplifier.rs | 5 ++++- rust/src/types.rs | 17 +++++++++----- 22 files changed, 142 insertions(+), 124 deletions(-) diff --git a/rust/src/architecture.rs b/rust/src/architecture.rs index 6ea7d9aac..e8e5e204b 100644 --- a/rust/src/architecture.rs +++ b/rust/src/architecture.rs @@ -24,7 +24,9 @@ use std::{ ffi::{c_char, c_int, CStr, CString}, hash::Hash, mem::{zeroed, MaybeUninit}, - ops, ptr, slice, + ops, + ptr, + slice, }; use crate::{ @@ -1087,7 +1089,7 @@ impl CoreArchitecture { } pub fn name(&self) -> BnString { - unsafe { BnString::from_raw(BNGetArchitectureName(self.0)) } + unsafe { BnString::from_raw(ptr::NonNull::new(BNGetArchitectureName(self.0)).unwrap()) } } } diff --git a/rust/src/backgroundtask.rs b/rust/src/backgroundtask.rs index e5fa6e77a..71275a9c7 100644 --- a/rust/src/backgroundtask.rs +++ b/rust/src/backgroundtask.rs @@ -16,6 +16,7 @@ use binaryninjacore_sys::*; +use std::ptr::NonNull; use std::result; use crate::rc::*; @@ -60,7 +61,9 @@ impl BackgroundTask { } pub fn get_progress_text(&self) -> BnString { - unsafe { BnString::from_raw(BNGetBackgroundTaskProgressText(self.handle)) } + unsafe { + BnString::from_raw(NonNull::new(BNGetBackgroundTaskProgressText(self.handle)).unwrap()) + } } pub fn cancel(&self) { diff --git a/rust/src/binaryview.rs b/rust/src/binaryview.rs index a4ed3332c..c03a9891c 100644 --- a/rust/src/binaryview.rs +++ b/rust/src/binaryview.rs @@ -194,7 +194,7 @@ pub trait BinaryViewExt: BinaryViewBase { fn type_name(&self) -> BnString { let ptr: *mut c_char = unsafe { BNGetViewType(self.as_ref().handle) }; - unsafe { BnString::from_raw(ptr) } + unsafe { BnString::from_raw(ptr::NonNull::new(ptr).unwrap()) } } fn parent_view(&self) -> Result> { @@ -222,7 +222,7 @@ pub trait BinaryViewExt: BinaryViewBase { fn view_type(&self) -> BnString { let ptr: *mut c_char = unsafe { BNGetViewType(self.as_ref().handle) }; - unsafe { BnString::from_raw(ptr) } + unsafe { BnString::from_raw(ptr::NonNull::new(ptr).unwrap()) } } /// Reads up to `len` bytes from address `offset` @@ -770,7 +770,7 @@ pub trait BinaryViewExt: BinaryViewBase { unsafe { let mut qualified_name = QualifiedName::from(name); let id_cstr = BNGetAnalysisTypeId(self.as_ref().handle, &mut qualified_name.0); - let id = BnString::from_raw(id_cstr); + let id = BnString::from_raw(ptr::NonNull::new(id_cstr).unwrap()); if id.is_empty() { return None; } diff --git a/rust/src/callingconvention.rs b/rust/src/callingconvention.rs index 9732e52f7..ffb28ddca 100644 --- a/rust/src/callingconvention.rs +++ b/rust/src/callingconvention.rs @@ -17,17 +17,13 @@ use std::borrow::Borrow; use std::fmt::{Debug, Formatter}; use std::marker::PhantomData; -use std::mem; use std::os::raw::c_void; -use std::ptr; -use std::slice; +use std::{mem, ptr, slice}; use binaryninjacore_sys::*; use crate::architecture::{Architecture, ArchitectureExt, CoreArchitecture, Register}; -use crate::rc::{ - CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable, -}; +use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; use crate::string::*; // TODO @@ -437,7 +433,9 @@ impl CallingConvention { } pub fn name(&self) -> BnString { - unsafe { BnString::from_raw(BNGetCallingConventionName(self.handle)) } + unsafe { + BnString::from_raw(NonNull::new(BNGetCallingConventionName(self.handle)).unwrap()) + } } pub fn variables_for_parameters( diff --git a/rust/src/custombinaryview.rs b/rust/src/custombinaryview.rs index 05f1acb8d..ca69ea16d 100644 --- a/rust/src/custombinaryview.rs +++ b/rust/src/custombinaryview.rs @@ -19,11 +19,9 @@ use binaryninjacore_sys::*; pub use binaryninjacore_sys::BNModificationStatus as ModificationStatus; use std::marker::PhantomData; -use std::mem; use std::mem::MaybeUninit; use std::os::raw::c_void; -use std::ptr; -use std::slice; +use std::{mem, ptr, slice}; use crate::architecture::Architecture; use crate::binaryview::{BinaryView, BinaryViewBase, BinaryViewExt, Result}; @@ -183,11 +181,17 @@ pub trait BinaryViewTypeBase: AsRef { pub trait BinaryViewTypeExt: BinaryViewTypeBase { fn name(&self) -> BnString { - unsafe { BnString::from_raw(BNGetBinaryViewTypeName(self.as_ref().0)) } + unsafe { + BnString::from_raw(ptr::NonNull::new(BNGetBinaryViewTypeName(self.as_ref().0)).unwrap()) + } } fn long_name(&self) -> BnString { - unsafe { BnString::from_raw(BNGetBinaryViewTypeLongName(self.as_ref().0)) } + unsafe { + BnString::from_raw( + ptr::NonNull::new(BNGetBinaryViewTypeLongName(self.as_ref().0)).unwrap(), + ) + } } fn register_arch(&self, id: u32, endianness: Endianness, arch: &A) { diff --git a/rust/src/debuginfo.rs b/rust/src/debuginfo.rs index c0232a1fa..44e3ca5d5 100644 --- a/rust/src/debuginfo.rs +++ b/rust/src/debuginfo.rs @@ -78,7 +78,12 @@ use crate::{ types::{DataVariableAndName, NameAndType, Type}, }; -use std::{hash::Hash, os::raw::c_void, ptr, slice}; +use std::{ + hash::Hash, + os::raw::c_void, + ptr::{self, NonNull}, + slice, +}; struct ProgressContext(Option Result<(), ()>>>); @@ -127,7 +132,7 @@ impl DebugInfoParser { /// Returns the name of the current parser pub fn name(&self) -> BnString { - unsafe { BnString::from_raw(BNGetDebugInfoParserName(self.handle)) } + unsafe { BnString::from_raw(NonNull::new(BNGetDebugInfoParserName(self.handle)).unwrap()) } } /// Returns whether this debug-info parser is valid for the provided binary view diff --git a/rust/src/disassembly.rs b/rust/src/disassembly.rs index 1fd51cee9..a693db2b8 100644 --- a/rust/src/disassembly.rs +++ b/rust/src/disassembly.rs @@ -23,8 +23,7 @@ use crate::rc::*; use std::convert::From; use std::ffi::CStr; -use std::mem; -use std::ptr; +use std::{mem, ptr}; pub type InstructionTextTokenType = BNInstructionTextTokenType; pub type InstructionTextTokenContext = BNInstructionTextTokenContext; @@ -257,7 +256,7 @@ impl Clone for InstructionTextToken { impl Drop for InstructionTextToken { fn drop(&mut self) { if !self.0.text.is_null() { - let _owned = unsafe { BnString::from_raw(self.0.text) }; + let _owned = unsafe { BnString::from_raw(ptr::NonNull::new(self.0.text).unwrap()) }; } if !self.0.typeNames.is_null() && self.0.namesCount != 0 { unsafe { BNFreeStringList(self.0.typeNames, self.0.namesCount) } diff --git a/rust/src/downloadprovider.rs b/rust/src/downloadprovider.rs index 0d388486e..49182a4ae 100644 --- a/rust/src/downloadprovider.rs +++ b/rust/src/downloadprovider.rs @@ -5,7 +5,7 @@ use binaryninjacore_sys::*; use std::collections::HashMap; use std::ffi::{c_void, CStr}; use std::os::raw::c_char; -use std::ptr::null_mut; +use std::ptr::{null_mut, NonNull}; use std::slice; pub struct DownloadProvider { @@ -106,7 +106,7 @@ impl DownloadInstance { fn get_error(&self) -> BnString { let err: *mut c_char = unsafe { BNGetErrorForDownloadInstance(self.handle) }; - unsafe { BnString::from_raw(err) } + unsafe { BnString::from_raw(NonNull::new(err).unwrap()) } } unsafe extern "C" fn o_write_callback(data: *mut u8, len: u64, ctxt: *mut c_void) -> u64 { diff --git a/rust/src/filemetadata.rs b/rust/src/filemetadata.rs index 0ef427c4e..61094c811 100644 --- a/rust/src/filemetadata.rs +++ b/rust/src/filemetadata.rs @@ -85,7 +85,7 @@ impl FileMetadata { pub fn filename(&self) -> BnString { unsafe { let raw = BNGetFilename(self.handle); - BnString::from_raw(raw) + BnString::from_raw(ptr::NonNull::new(raw).unwrap()) } } @@ -142,7 +142,10 @@ impl FileMetadata { } pub fn begin_undo_actions(&self, anonymous_allowed: bool) -> BnString { - unsafe { BnString::from_raw(BNBeginUndoActions(self.handle, anonymous_allowed)) } + unsafe { + let result = BNBeginUndoActions(self.handle, anonymous_allowed); + BnString::from_raw(ptr::NonNull::new(result).unwrap()) + } } pub fn commit_undo_actions(&self, id: S) { @@ -172,7 +175,7 @@ impl FileMetadata { } pub fn current_view(&self) -> BnString { - unsafe { BnString::from_raw(BNGetCurrentView(self.handle)) } + unsafe { BnString::from_raw(ptr::NonNull::new(BNGetCurrentView(self.handle)).unwrap()) } } pub fn current_offset(&self) -> u64 { diff --git a/rust/src/function.rs b/rust/src/function.rs index dce724417..d4bc688d7 100644 --- a/rust/src/function.rs +++ b/rust/src/function.rs @@ -184,7 +184,7 @@ impl Function { } pub fn comment(&self) -> BnString { - unsafe { BnString::from_raw(BNGetFunctionComment(self.handle)) } + unsafe { BnString::from_raw(NonNull::new(BNGetFunctionComment(self.handle)).unwrap()) } } pub fn set_comment(&self, comment: S) { @@ -206,7 +206,9 @@ impl Function { } pub fn comment_at(&self, addr: u64) -> BnString { - unsafe { BnString::from_raw(BNGetCommentForAddress(self.handle, addr)) } + unsafe { + BnString::from_raw(NonNull::new(BNGetCommentForAddress(self.handle, addr)).unwrap()) + } } pub fn set_comment_at(&self, addr: u64, comment: S) { @@ -279,7 +281,7 @@ impl Function { unsafe { let raw_var = var.raw(); let raw_name = BNGetVariableName(self.handle, &raw_var); - BnString::from_raw(raw_name) + BnString::from_raw(NonNull::new(raw_name).unwrap()) } } @@ -1536,15 +1538,16 @@ impl Function { arch: Option, ) -> BnString { let arch = arch.unwrap_or_else(|| self.arch()); - unsafe { - BnString::from_raw(BNGetIntegerConstantDisplayTypeEnumerationType( + let result = unsafe { + BNGetIntegerConstantDisplayTypeEnumerationType( self.handle, arch.0, instr_addr, value, operand, - )) - } + ) + }; + unsafe { BnString::from_raw(NonNull::new(result).unwrap()) } } /// Get the current text display type for an integer token in the disassembly or IL views @@ -1721,7 +1724,7 @@ impl Function { return None; } let var = unsafe { Variable::from_raw(found_value.var) }; - let name = unsafe { BnString::from_raw(found_value.name) }; + let name = unsafe { BnString::from_raw(NonNull::new(found_value.name).unwrap()) }; let var_type = Conf::new( unsafe { Type::from_raw(NonNull::new(found_value.type_).unwrap()) }, found_value.typeConfidence, @@ -2093,7 +2096,7 @@ impl Function { /// is under develoment. 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)) } + unsafe { BnString::from_raw(NonNull::new(BNGetProvenanceString(self.handle)).unwrap()) } } /// Get registers that are used for the return value diff --git a/rust/src/hlil/operation.rs b/rust/src/hlil/operation.rs index e762a74bc..0461bcac2 100644 --- a/rust/src/hlil/operation.rs +++ b/rust/src/hlil/operation.rs @@ -1,3 +1,5 @@ +use std::ptr::NonNull; + use binaryninjacore_sys::BNGetGotoLabelName; use crate::architecture::CoreIntrinsic; @@ -16,7 +18,8 @@ pub struct GotoLabel { impl GotoLabel { pub fn name(&self) -> BnString { - unsafe { BnString::from_raw(BNGetGotoLabelName(self.function.handle, self.target)) } + let result = unsafe { BNGetGotoLabelName(self.function.handle, self.target) }; + unsafe { BnString::from_raw(NonNull::new(result).unwrap()) } } } diff --git a/rust/src/interaction.rs b/rust/src/interaction.rs index 7d10bbe4a..e25c94165 100644 --- a/rust/src/interaction.rs +++ b/rust/src/interaction.rs @@ -19,6 +19,7 @@ use binaryninjacore_sys::*; use std::ffi::CStr; use std::os::raw::{c_char, c_void}; use std::path::PathBuf; +use std::ptr::NonNull; use crate::binaryview::BinaryView; use crate::rc::Ref; @@ -38,7 +39,7 @@ pub fn get_text_line_input(prompt: &str, title: &str) -> Option { return None; } - Some(unsafe { BnString::from_raw(value).to_string() }) + Some(unsafe { BnString::from_raw(NonNull::new(value).unwrap()).to_string() }) } pub fn get_integer_input(prompt: &str, title: &str) -> Option { @@ -93,7 +94,7 @@ pub fn get_open_filename_input(prompt: &str, extension: &str) -> Option return None; } - let string = unsafe { BnString::from_raw(value) }; + let string = unsafe { BnString::from_raw(NonNull::new(value).unwrap()) }; Some(PathBuf::from(string.as_str())) } @@ -112,7 +113,7 @@ pub fn get_save_filename_input(prompt: &str, title: &str, default_name: &str) -> return None; } - let string = unsafe { BnString::from_raw(value) }; + let string = unsafe { BnString::from_raw(NonNull::new(value).unwrap()) }; Some(PathBuf::from(string.as_str())) } @@ -130,7 +131,7 @@ pub fn get_directory_name_input(prompt: &str, default_name: &str) -> Option( pub fn install_directory() -> Result { let s: *mut std::os::raw::c_char = unsafe { binaryninjacore_sys::BNGetInstallDirectory() }; - if s.is_null() { - return Err(()); - } + let s = NonNull::new(s).ok_or(())?; Ok(PathBuf::from( unsafe { string::BnString::from_raw(s) }.to_string(), )) @@ -282,9 +281,7 @@ pub fn install_directory() -> Result { pub fn bundled_plugin_directory() -> Result { let s: *mut std::os::raw::c_char = unsafe { binaryninjacore_sys::BNGetBundledPluginDirectory() }; - if s.is_null() { - return Err(()); - } + let s = NonNull::new(s).ok_or(())?; Ok(PathBuf::from( unsafe { string::BnString::from_raw(s) }.to_string(), )) @@ -300,9 +297,7 @@ pub fn set_bundled_plugin_directory(new_dir: S) { pub fn user_directory() -> Result { let s: *mut std::os::raw::c_char = unsafe { binaryninjacore_sys::BNGetUserDirectory() }; - if s.is_null() { - return Err(()); - } + let s = NonNull::new(s).ok_or(())?; Ok(PathBuf::from( unsafe { string::BnString::from_raw(s) }.to_string(), )) @@ -310,9 +305,7 @@ pub fn user_directory() -> Result { pub fn user_plugin_directory() -> Result { let s: *mut std::os::raw::c_char = unsafe { binaryninjacore_sys::BNGetUserPluginDirectory() }; - if s.is_null() { - return Err(()); - } + let s = NonNull::new(s).ok_or(())?; Ok(PathBuf::from( unsafe { string::BnString::from_raw(s) }.to_string(), )) @@ -320,9 +313,7 @@ pub fn user_plugin_directory() -> Result { pub fn repositories_directory() -> Result { let s: *mut std::os::raw::c_char = unsafe { binaryninjacore_sys::BNGetRepositoriesDirectory() }; - if s.is_null() { - return Err(()); - } + let s = NonNull::new(s).ok_or(())?; Ok(PathBuf::from( unsafe { string::BnString::from_raw(s) }.to_string(), )) @@ -330,9 +321,7 @@ pub fn repositories_directory() -> Result { pub fn settings_file_name() -> Result { let s: *mut std::os::raw::c_char = unsafe { binaryninjacore_sys::BNGetSettingsFileName() }; - if s.is_null() { - return Err(()); - } + let s = NonNull::new(s).ok_or(())?; Ok(PathBuf::from( unsafe { string::BnString::from_raw(s) }.to_string(), )) @@ -350,9 +339,7 @@ pub fn path_relative_to_bundled_plugin_directory( path.into_bytes_with_nul().as_ref().as_ptr() as *const std::os::raw::c_char, ) }; - if s.is_null() { - return Err(()); - } + let s = NonNull::new(s).ok_or(())?; Ok(PathBuf::from( unsafe { string::BnString::from_raw(s) }.to_string(), )) @@ -366,9 +353,7 @@ pub fn path_relative_to_user_plugin_directory( path.into_bytes_with_nul().as_ref().as_ptr() as *const std::os::raw::c_char, ) }; - if s.is_null() { - return Err(()); - } + let s = NonNull::new(s).ok_or(())?; Ok(PathBuf::from( unsafe { string::BnString::from_raw(s) }.to_string(), )) @@ -380,16 +365,16 @@ pub fn path_relative_to_user_directory(path: S) -> R path.into_bytes_with_nul().as_ref().as_ptr() as *const std::os::raw::c_char, ) }; - if s.is_null() { - return Err(()); - } + let s = NonNull::new(s).ok_or(())?; Ok(PathBuf::from( unsafe { string::BnString::from_raw(s) }.to_string(), )) } pub fn version() -> string::BnString { - unsafe { string::BnString::from_raw(binaryninjacore_sys::BNGetVersionString()) } + unsafe { + string::BnString::from_raw(NonNull::new(binaryninjacore_sys::BNGetVersionString()).unwrap()) + } } pub fn plugin_abi_version() -> u32 { diff --git a/rust/src/metadata.rs b/rust/src/metadata.rs index 9eeff8fad..44ced0267 100644 --- a/rust/src/metadata.rs +++ b/rust/src/metadata.rs @@ -3,6 +3,7 @@ use crate::string::{BnStrCompatible, BnString, IntoJson}; use binaryninjacore_sys::*; use std::collections::HashMap; use std::os::raw::c_char; +use std::ptr::NonNull; use std::slice; pub type MetadataType = BNMetadataType; @@ -69,7 +70,7 @@ impl Metadata { if ptr.is_null() { return Err(()); } - Ok(unsafe { BnString::from_raw(ptr) }) + Ok(unsafe { BnString::from_raw(NonNull::new(ptr).unwrap()) }) } _ => Err(()), } @@ -157,7 +158,7 @@ impl Metadata { let list = unsafe { slice::from_raw_parts(ptr, size) }; let vec = list .iter() - .map(|ptr| unsafe { BnString::from_raw(*ptr) }) + .map(|ptr| unsafe { BnString::from_raw(NonNull::new(*ptr).unwrap()) }) .collect::>(); unsafe { BNFreeMetadataStringList(ptr, size) }; Ok(vec) @@ -173,7 +174,7 @@ impl Metadata { if ptr.is_null() { return Err(()); } - Ok(unsafe { BnString::from_raw(ptr) }) + Ok(unsafe { BnString::from_raw(NonNull::new(ptr).unwrap()) }) } _ => Err(()), } @@ -230,7 +231,7 @@ impl Metadata { let mut map = HashMap::new(); for i in 0..size { - let key = unsafe { BnString::from_raw(keys[i]) }; + let key = unsafe { BnString::from_raw(NonNull::new(keys[i]).unwrap()) }; let value = unsafe { Ref::::new(Self { diff --git a/rust/src/platform.rs b/rust/src/platform.rs index 2af76916c..1bc505986 100644 --- a/rust/src/platform.rs +++ b/rust/src/platform.rs @@ -18,6 +18,7 @@ use std::borrow::Borrow; use std::collections::HashMap; use std::os::raw; use std::path::Path; +use std::ptr::NonNull; use std::{ptr, slice}; use binaryninjacore_sys::*; @@ -157,7 +158,7 @@ impl Platform { pub fn name(&self) -> BnString { unsafe { let raw_name = BNGetPlatformName(self.handle); - BnString::from_raw(raw_name) + BnString::from_raw(NonNull::new(raw_name).unwrap()) } } @@ -312,7 +313,7 @@ impl TypeParser for Platform { auto_type_source.as_ref().as_ptr() as _, ); - let error_msg = BnString::from_raw(error_string); + let error_msg = BnString::from_raw(NonNull::new(error_string).unwrap()); if !success { return Err(error_msg.to_string()); diff --git a/rust/src/section.rs b/rust/src/section.rs index 1e45db8b5..f0eac5e39 100644 --- a/rust/src/section.rs +++ b/rust/src/section.rs @@ -16,6 +16,7 @@ use std::fmt; use std::ops::Range; +use std::ptr::NonNull; use binaryninjacore_sys::*; @@ -83,11 +84,11 @@ impl Section { } pub fn name(&self) -> BnString { - unsafe { BnString::from_raw(BNSectionGetName(self.handle)) } + unsafe { BnString::from_raw(NonNull::new(BNSectionGetName(self.handle)).unwrap()) } } pub fn section_type(&self) -> BnString { - unsafe { BnString::from_raw(BNSectionGetType(self.handle)) } + unsafe { BnString::from_raw(NonNull::new(BNSectionGetType(self.handle)).unwrap()) } } pub fn start(&self) -> u64 { @@ -115,11 +116,11 @@ impl Section { } pub fn linked_section(&self) -> BnString { - unsafe { BnString::from_raw(BNSectionGetLinkedSection(self.handle)) } + unsafe { BnString::from_raw(NonNull::new(BNSectionGetLinkedSection(self.handle)).unwrap()) } } pub fn info_section(&self) -> BnString { - unsafe { BnString::from_raw(BNSectionGetInfoSection(self.handle)) } + unsafe { BnString::from_raw(NonNull::new(BNSectionGetInfoSection(self.handle)).unwrap()) } } pub fn info_data(&self) -> u64 { diff --git a/rust/src/settings.rs b/rust/src/settings.rs index 3ec3e4063..a8f421f60 100644 --- a/rust/src/settings.rs +++ b/rust/src/settings.rs @@ -16,15 +16,15 @@ pub use binaryninjacore_sys::BNSettingsScope as SettingsScope; use binaryninjacore_sys::*; + use std::iter::FromIterator; use std::os::raw::c_char; +use std::ptr; use crate::binaryview::BinaryView; use crate::rc::*; use crate::string::{BnStrCompatible, BnString}; -use std::ptr; - #[derive(PartialEq, Eq, Hash)] pub struct Settings { pub(crate) handle: *mut BNSettings, @@ -57,7 +57,7 @@ impl Settings { } pub fn serialize_schema(&self) -> BnString { - unsafe { BnString::from_raw(BNSettingsSerializeSchema(self.handle)) } + unsafe { BnString::from_raw(ptr::NonNull::new(BNSettingsSerializeSchema(self.handle)).unwrap()) } } pub fn deserialize_schema(&self, schema: S) -> bool { @@ -168,14 +168,15 @@ impl Settings { Some(mut scope) => scope.as_mut(), _ => ptr::null_mut() as *mut _, }; - unsafe { - BnString::from_raw(BNSettingsGetString( + let result = unsafe { + BNSettingsGetString( self.handle, key.as_ref().as_ptr() as *mut _, view_handle, scope_ptr, - )) - } + ) + }; + unsafe { BnString::from_raw(ptr::NonNull::new(result).unwrap()) } } pub fn get_string_list( @@ -224,14 +225,15 @@ impl Settings { Some(mut scope) => scope.as_mut(), _ => ptr::null_mut() as *mut _, }; - unsafe { - BnString::from_raw(BNSettingsGetJson( + let result = unsafe { + BNSettingsGetJson( self.handle, key.as_ref().as_ptr() as *mut _, view_handle, scope_ptr, - )) - } + ) + }; + unsafe { BnString::from_raw(ptr::NonNull::new(result).unwrap()) } } pub fn set_bool( diff --git a/rust/src/string.rs b/rust/src/string.rs index 936e30334..a497ff8c3 100644 --- a/rust/src/string.rs +++ b/rust/src/string.rs @@ -16,11 +16,11 @@ use std::borrow::Cow; use std::ffi::{CStr, CString}; -use std::fmt; use std::hash::{Hash, Hasher}; -use std::mem; use std::ops::Deref; use std::os::raw; +use std::ptr::NonNull; +use std::{fmt, mem}; use crate::rc::*; use crate::types::QualifiedName; @@ -37,7 +37,7 @@ pub(crate) fn raw_to_string(ptr: *const raw::c_char) -> Option { /// functions provided by binaryninja_sys. #[repr(transparent)] pub struct BnString { - raw: *mut raw::c_char, + raw: NonNull, } /// A nul-terminated C string allocated by the core. @@ -59,28 +59,28 @@ impl BnString { let ptr = raw.as_ref().as_ptr() as *mut _; Self { - raw: BNAllocString(ptr), + raw: NonNull::new(BNAllocString(ptr)).unwrap(), } } } /// Construct a BnString from an owned const char* allocated by BNAllocString - pub(crate) unsafe fn from_raw(raw: *mut raw::c_char) -> Self { + pub(crate) unsafe fn from_raw(raw: NonNull) -> Self { Self { raw } } - pub(crate) fn into_raw(self) -> *mut raw::c_char { - let res = self.raw; + pub(crate) fn as_raw(&self) -> &raw::c_char { + unsafe { &*self.raw.as_ptr() } + } + pub(crate) fn into_raw(self) -> *mut raw::c_char { // we're surrendering ownership over the *mut c_char to // the core, so ensure we don't free it - mem::forget(self); - - res + mem::ManuallyDrop::new(self).raw.as_ptr() } pub fn as_str(&self) -> &str { - unsafe { CStr::from_ptr(self.raw).to_str().unwrap() } + unsafe { CStr::from_ptr(self.raw.as_ptr()).to_str().unwrap() } } pub fn as_bytes(&self) -> &[u8] { @@ -104,9 +104,7 @@ impl Drop for BnString { fn drop(&mut self) { use binaryninjacore_sys::BNFreeString; - unsafe { - BNFreeString(self.raw); - } + unsafe { BNFreeString(self.as_raw() as *const raw::c_char as *mut raw::c_char) }; } } @@ -115,7 +113,7 @@ impl Clone for BnString { use binaryninjacore_sys::BNAllocString; unsafe { Self { - raw: BNAllocString(self.raw), + raw: NonNull::new(BNAllocString(self.as_raw())).unwrap(), } } } @@ -125,7 +123,7 @@ impl Deref for BnString { type Target = CStr; fn deref(&self) -> &CStr { - unsafe { CStr::from_ptr(self.raw) } + unsafe { CStr::from_ptr(self.as_raw()) } } } diff --git a/rust/src/symbol.rs b/rust/src/symbol.rs index d7a73a0ae..a6e8c889c 100644 --- a/rust/src/symbol.rs +++ b/rust/src/symbol.rs @@ -14,9 +14,8 @@ //! Interfaces for the various kinds of symbols in a binary. -use std::fmt; use std::hash::{Hash, Hasher}; -use std::ptr; +use std::{fmt, ptr}; use crate::rc::*; use crate::string::*; @@ -248,15 +247,15 @@ impl Symbol { } pub fn full_name(&self) -> BnString { - unsafe { BnString::from_raw(BNGetSymbolFullName(self.handle)) } + unsafe { BnString::from_raw(ptr::NonNull::new(BNGetSymbolFullName(self.handle)).unwrap()) } } pub fn short_name(&self) -> BnString { - unsafe { BnString::from_raw(BNGetSymbolShortName(self.handle)) } + unsafe { BnString::from_raw(ptr::NonNull::new(BNGetSymbolShortName(self.handle)).unwrap()) } } pub fn raw_name(&self) -> BnString { - unsafe { BnString::from_raw(BNGetSymbolRawName(self.handle)) } + unsafe { BnString::from_raw(ptr::NonNull::new(BNGetSymbolRawName(self.handle)).unwrap()) } } pub fn address(&self) -> u64 { diff --git a/rust/src/tags.rs b/rust/src/tags.rs index 912ee81b1..84ec3bcde 100644 --- a/rust/src/tags.rs +++ b/rust/src/tags.rs @@ -14,6 +14,8 @@ //! Interfaces for creating and modifying tags in a BinaryView. +use std::ptr::NonNull; + use binaryninjacore_sys::*; use crate::architecture::CoreArchitecture; @@ -40,11 +42,11 @@ impl Tag { } pub fn id(&self) -> BnString { - unsafe { BnString::from_raw(BNTagGetId(self.handle)) } + unsafe { BnString::from_raw(NonNull::new(BNTagGetId(self.handle)).unwrap()) } } pub fn data(&self) -> BnString { - unsafe { BnString::from_raw(BNTagGetData(self.handle)) } + unsafe { BnString::from_raw(NonNull::new(BNTagGetData(self.handle)).unwrap()) } } pub fn t(&self) -> Ref { @@ -122,11 +124,11 @@ impl TagType { } pub fn id(&self) -> BnString { - unsafe { BnString::from_raw(BNTagTypeGetId(self.handle)) } + unsafe { BnString::from_raw(NonNull::new(BNTagTypeGetId(self.handle)).unwrap()) } } pub fn icon(&self) -> BnString { - unsafe { BnString::from_raw(BNTagTypeGetIcon(self.handle)) } + unsafe { BnString::from_raw(NonNull::new(BNTagTypeGetIcon(self.handle)).unwrap()) } } pub fn set_icon(&self, icon: S) { @@ -137,7 +139,7 @@ impl TagType { } pub fn name(&self) -> BnString { - unsafe { BnString::from_raw(BNTagTypeGetName(self.handle)) } + unsafe { BnString::from_raw(NonNull::new(BNTagTypeGetName(self.handle)).unwrap()) } } pub fn set_name(&self, name: S) { diff --git a/rust/src/templatesimplifier.rs b/rust/src/templatesimplifier.rs index 5959167da..2c2e00c13 100644 --- a/rust/src/templatesimplifier.rs +++ b/rust/src/templatesimplifier.rs @@ -1,3 +1,5 @@ +use std::ptr::NonNull; + use crate::{ string::{BnStrCompatible, BnString}, types::QualifiedName, @@ -6,7 +8,8 @@ use binaryninjacore_sys::{BNRustSimplifyStrToFQN, BNRustSimplifyStrToStr}; pub fn simplify_str_to_str(input: S) -> BnString { let name = input.into_bytes_with_nul(); - unsafe { BnString::from_raw(BNRustSimplifyStrToStr(name.as_ref().as_ptr() as *mut _)) } + let result = unsafe { BNRustSimplifyStrToStr(name.as_ref().as_ptr() as *mut _) }; + unsafe { BnString::from_raw(NonNull::new(result).unwrap()) } } pub fn simplify_str_to_fqn(input: S, simplify: bool) -> QualifiedName { diff --git a/rust/src/types.rs b/rust/src/types.rs index ca36ea4f1..0ba5b1401 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -694,7 +694,9 @@ impl TypeBuilder { impl fmt::Display for TypeBuilder { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", unsafe { - BnString::from_raw(BNGetTypeBuilderString(self.as_raw(), ptr::null_mut())) + BnString::from_raw( + NonNull::new(BNGetTypeBuilderString(self.as_raw(), ptr::null_mut())).unwrap(), + ) }) } } @@ -1222,18 +1224,21 @@ impl Type { pub fn generate_auto_demangled_type_id(name: S) -> BnString { let mut name = QualifiedName::from(name); - unsafe { BnString::from_raw(BNGenerateAutoDemangledTypeId(&mut name.0)) } + unsafe { + BnString::from_raw(NonNull::new(BNGenerateAutoDemangledTypeId(&mut name.0)).unwrap()) + } } } impl fmt::Display for Type { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", unsafe { - BnString::from_raw(BNGetTypeString( + let result = BNGetTypeString( self.as_raw(), ptr::null_mut(), BNTokenEscapingType::NoTokenEscapingType, - )) + ); + BnString::from_raw(NonNull::new(result).unwrap()) }) } } @@ -2312,7 +2317,7 @@ impl NamedTypeReference { } pub fn id(&self) -> BnString { - unsafe { BnString::from_raw(BNGetTypeReferenceId(self.handle)) } + unsafe { BnString::from_raw(NonNull::new(BNGetTypeReferenceId(self.handle)).unwrap()) } } pub fn class(&self) -> NamedTypeReferenceClass { @@ -3574,7 +3579,7 @@ impl StackVariableReference { unsafe { Type::from_raw(NonNull::new(value.type_).unwrap()) }, value.typeConfidence, ); - let name = unsafe { BnString::from_raw(value.name) }; + let name = unsafe { BnString::from_raw(NonNull::new(value.name).unwrap()) }; let var = unsafe { Variable::from_identifier(value.varIdentifier) }; let offset = value.referencedOffset; let size = value.size; From 4bae1fda99502bd6892ad0817f868f30c0c88705 Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Wed, 29 May 2024 13:04:12 -0300 Subject: [PATCH 04/33] change `FunctionParameter` to the new standard --- rust/src/callingconvention.rs | 21 +----- rust/src/types.rs | 136 +++++++++++++++++----------------- 2 files changed, 71 insertions(+), 86 deletions(-) diff --git a/rust/src/callingconvention.rs b/rust/src/callingconvention.rs index ffb28ddca..163292c46 100644 --- a/rust/src/callingconvention.rs +++ b/rust/src/callingconvention.rs @@ -434,7 +434,7 @@ impl CallingConvention { pub fn name(&self) -> BnString { unsafe { - BnString::from_raw(NonNull::new(BNGetCallingConventionName(self.handle)).unwrap()) + BnString::from_raw(ptr::NonNull::new(BNGetCallingConventionName(self.handle)).unwrap()) } } @@ -443,22 +443,9 @@ impl CallingConvention { params: &[FunctionParameter], permitted_registers: Option<&[A::Register]>, ) -> Vec { - let mut bn_params: Vec = vec![]; - let name_strings = params.iter().map(|parameter| ¶meter.name); - - for (parameter, raw_name) in params.iter().zip(name_strings) { - let location = match ¶meter.location { - Some(location) => location.raw(), - None => unsafe { mem::zeroed() }, - }; - bn_params.push(BNFunctionParameter { - name: BnString::new(raw_name).into_raw(), - type_: parameter.t.contents.as_raw(), - typeConfidence: parameter.t.confidence, - defaultLocation: parameter.location.is_none(), - location, - }); - } + // SAFETY: FunctionParameter and BNFunctionParameter are transparent, + // so this can be safelly transmuted + let bn_params: &[BNFunctionParameter] = unsafe { mem::transmute(params) }; let mut count: usize = 0; let vars: *mut BNVariable = if let Some(permitted_args) = permitted_registers { diff --git a/rust/src/types.rs b/rust/src/types.rs index 0ba5b1401..4fe2df3e0 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -37,7 +37,7 @@ use std::{ ffi::CStr, fmt::{self, Debug, Display, Formatter}, hash::{Hash, Hasher}, - iter::{zip, IntoIterator}, + iter::IntoIterator, mem::{self, ManuallyDrop}, ops::Range, os::raw::c_char, @@ -1029,24 +1029,9 @@ impl Type { }; let mut stack_adjust = Conf::::new(0, min_confidence()).into(); - let mut raw_parameters = Vec::::with_capacity(parameters.len()); - let mut parameter_name_references = Vec::with_capacity(parameters.len()); - for parameter in parameters { - let raw_name = parameter.name.as_str().into_bytes_with_nul(); - let location = match ¶meter.location { - Some(location) => location.raw(), - None => unsafe { mem::zeroed() }, - }; - - raw_parameters.push(BNFunctionParameter { - name: raw_name.as_slice().as_ptr() as *mut _, - type_: parameter.t.contents.as_raw(), - typeConfidence: parameter.t.confidence, - defaultLocation: parameter.location.is_none(), - location, - }); - parameter_name_references.push(raw_name); - } + // SAFETY: FunctionParameter and BNFunctionParameter are transparent, + // so this can be safelly transmuted + let raw_parameters: &[BNFunctionParameter] = unsafe { mem::transmute(parameters) }; let reg_stack_adjust_regs = ptr::null_mut(); let reg_stack_adjust_values = ptr::null_mut(); @@ -1060,7 +1045,7 @@ impl Type { let result = BNNewTypeReference(BNCreateFunctionType( &mut return_type, &mut raw_calling_convention, - raw_parameters.as_mut_ptr(), + raw_parameters.as_ptr() as *mut BNFunctionParameter, raw_parameters.len(), &mut variable_arguments, &mut can_return, @@ -1096,29 +1081,14 @@ impl Type { calling_convention.into().into(); let mut stack_adjust = stack_adjust.into(); - let mut raw_parameters = Vec::::with_capacity(parameters.len()); - let mut parameter_name_references = Vec::with_capacity(parameters.len()); let mut name_ptrs = vec![]; for parameter in parameters { - name_ptrs.push(parameter.name.clone()); + name_ptrs.push(parameter.name().clone()); } - for (name, parameter) in zip(name_ptrs, parameters) { - let raw_name = name.as_str().into_bytes_with_nul(); - let location = match ¶meter.location { - Some(location) => location.raw(), - None => unsafe { mem::zeroed() }, - }; - - raw_parameters.push(BNFunctionParameter { - name: raw_name.as_slice().as_ptr() as *mut _, - type_: parameter.t.contents.as_raw(), - typeConfidence: parameter.t.confidence, - defaultLocation: parameter.location.is_none(), - location, - }); - parameter_name_references.push(raw_name); - } + // SAFETY: FunctionParameter and BNFunctionParameter are transparent, + // so this can be safelly transmuted + let raw_parameters: &[BNFunctionParameter] = unsafe { mem::transmute(parameters) }; // TODO: Update type signature and include these (will be a breaking change) let reg_stack_adjust_regs = ptr::null_mut(); @@ -1134,7 +1104,7 @@ impl Type { let result = BNCreateFunctionType( &mut return_type, &mut raw_calling_convention, - raw_parameters.as_mut_ptr(), + raw_parameters.as_ptr() as *mut BNFunctionParameter, raw_parameters.len(), &mut variable_arguments, &mut can_return, @@ -1333,49 +1303,76 @@ impl Drop for Type { /////////////////////// // FunctionParameter +#[repr(C)] #[derive(Clone, Debug)] pub struct FunctionParameter { - pub t: Conf, - pub name: String, - pub location: Option, + name: Option, + pub t: Type, + type_confidence: u8, + default_location: bool, + location: Variable, } impl FunctionParameter { - pub fn new>>(t: T, name: String, location: Option) -> Self { + pub fn new>>( + t: T, + name: S, + location: Option, + ) -> Self { + let t = t.into(); + let dummy_var: Variable = + Variable::new(BNVariableSourceType::StackVariableSourceType, 0, 0); Self { - t: t.into(), - name, - location, + name: Some(BnString::new(name)), + t: t.contents, + type_confidence: t.confidence, + default_location: location.is_some(), + location: location.unwrap_or(dummy_var), } } - pub(crate) fn from_raw(member: BNFunctionParameter) -> Self { - let name = if member.name.is_null() { - if member.location.type_ == BNVariableSourceType::RegisterVariableSourceType { - format!("reg_{}", member.location.storage) - } else if member.location.type_ == BNVariableSourceType::StackVariableSourceType { - format!("arg_{}", member.location.storage) - } else { - String::new() - } + pub(crate) unsafe fn from_raw(member: BNFunctionParameter) -> Self { + let name = NonNull::new(member.name).map(|name| unsafe { BnString::from_raw(name) }); + + let location = if member.defaultLocation { + // dummy value + Variable::new(BNVariableSourceType::StackVariableSourceType, 0, 0) } else { - unsafe { CStr::from_ptr(member.name) } - .to_str() - .unwrap() - .to_owned() + unsafe { Variable::from_raw(member.location) } }; Self { - t: Conf::new( - unsafe { Type::from_raw(NonNull::new(BNNewTypeReference(member.type_)).unwrap()) }, - member.typeConfidence, - ), + t: unsafe { Type::from_raw(NonNull::new(BNNewTypeReference(member.type_)).unwrap()) }, + type_confidence: member.typeConfidence, name, - location: if member.defaultLocation { - None - } else { - Some(unsafe { Variable::from_raw(member.location) }) - }, + default_location: member.defaultLocation, + location, + } + } + + pub fn location(&self) -> Option { + (!self.default_location).then_some(self.location) + } + + pub fn name(&self) -> Cow { + if let Some(name) = &self.name { + Cow::Borrowed(name.as_str()) + } else { + match self.location() { + Some(Variable { + t: BNVariableSourceType::RegisterVariableSourceType, + .. + }) => Cow::Owned(format!("reg_{}", self.location.storage)), + Some(Variable { + t: BNVariableSourceType::StackVariableSourceType, + .. + }) => Cow::Owned(format!("arg_{}", self.location.storage)), + Some(Variable { + t: BNVariableSourceType::FlagVariableSourceType, + .. + }) + | None => Cow::Borrowed(""), + } } } } @@ -1383,6 +1380,7 @@ impl FunctionParameter { ////////////// // Variable +#[repr(C)] #[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] pub struct Variable { pub t: BNVariableSourceType, From 3e18469cecdbe01518005949380be9d4459cf70e Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Wed, 29 May 2024 13:16:00 -0300 Subject: [PATCH 05/33] change `NamedTypedVariable` to the new standard --- rust/src/types.rs | 46 +++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/rust/src/types.rs b/rust/src/types.rs index 4fe2df3e0..1c1c32b55 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -1503,40 +1503,58 @@ unsafe impl CoreArrayProviderInner for Array { /////////////// // NamedVariable +#[repr(C)] +#[derive(Debug, Clone)] pub struct NamedTypedVariable { - var: BNVariable, + var: Variable, + // ManuallyDrop because this is droped by the BNFreeVariableNameAndType + // and not but Type::drop and BnString::drop + ty: ManuallyDrop, + name: ManuallyDrop, auto_defined: bool, type_confidence: u8, - name: *mut c_char, - ty: *mut BNType, } impl NamedTypedVariable { + pub(crate) unsafe fn ref_from_raw(handle: &BNVariableNameAndType) -> &Self { + assert!(!handle.type_.is_null()); + assert!(!handle.name.is_null()); + mem::transmute(handle) + } + + pub(crate) fn as_raw(&self) -> &BNVariableNameAndType { + unsafe { mem::transmute(self) } + } + pub fn name(&self) -> &str { - unsafe { CStr::from_ptr(self.name).to_str().unwrap() } + self.name.as_str() } pub fn var(&self) -> Variable { - unsafe { Variable::from_raw(self.var) } + self.var } pub fn auto_defined(&self) -> bool { self.auto_defined } - pub fn type_confidence(&self) -> u8 { - self.type_confidence + pub fn var_type(&self) -> Conf<&Type> { + Conf::new(&self.ty, self.type_confidence) } +} - pub fn var_type(&self) -> Type { - unsafe { Type::from_raw(NonNull::new(self.ty).unwrap()) } +impl Drop for NamedTypedVariable { + fn drop(&mut self) { + unsafe { + BNFreeVariableNameAndType(self.as_raw() as *const _ as *mut BNVariableNameAndType) + } } } impl CoreArrayProvider for NamedTypedVariable { type Raw = BNVariableNameAndType; type Context = (); - type Wrapped<'a> = ManuallyDrop; + type Wrapped<'a> = &'a NamedTypedVariable; } unsafe impl CoreArrayProviderInner for NamedTypedVariable { @@ -1544,13 +1562,7 @@ unsafe impl CoreArrayProviderInner for NamedTypedVariable { BNFreeVariableNameAndTypeList(raw, count) } unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> { - ManuallyDrop::new(NamedTypedVariable { - var: raw.var, - ty: raw.type_, - name: raw.name, - auto_defined: raw.autoDefined, - type_confidence: raw.typeConfidence, - }) + Self::ref_from_raw(raw) } } From 3d87df262bbe8d711e1b76655eb269ef9ffce4bb Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Wed, 29 May 2024 13:29:17 -0300 Subject: [PATCH 06/33] change `EnumerationBuilder` to the new standard --- rust/src/types.rs | 51 ++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/rust/src/types.rs b/rust/src/types.rs index 1c1c32b55..df8ca304a 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -1569,55 +1569,56 @@ unsafe impl CoreArrayProviderInner for NamedTypedVariable { //////////////////////// // EnumerationBuilder +#[repr(C)] #[derive(Debug, Clone)] pub struct EnumerationMember { - pub name: String, + pub name: BnString, pub value: u64, pub is_default: bool, } impl EnumerationMember { - pub fn new(name: String, value: u64, is_default: bool) -> Self { + pub fn new(name: S, value: u64, is_default: bool) -> Self { Self { - name, + name: BnString::new(name), value, is_default, } } pub(crate) unsafe fn from_raw(member: BNEnumerationMember) -> Self { - Self { - name: raw_to_string(member.name).unwrap(), - value: member.value, - is_default: member.isDefault, - } + mem::transmute(member) } } #[derive(PartialEq, Eq, Hash)] pub struct EnumerationBuilder { - pub(crate) handle: *mut BNEnumerationBuilder, + handle: NonNull, } impl EnumerationBuilder { pub fn new() -> Self { Self { - handle: unsafe { BNCreateEnumerationBuilder() }, + handle: NonNull::new(unsafe { BNCreateEnumerationBuilder() }).unwrap(), } } - pub(crate) unsafe fn from_raw(handle: *mut BNEnumerationBuilder) -> Self { + pub(crate) unsafe fn from_raw(handle: NonNull) -> Self { Self { handle } } + pub(crate) fn as_raw(&self) -> &mut BNEnumerationBuilder { + unsafe { &mut (*self.handle.as_ptr()) } + } + pub fn finalize(&self) -> Ref { - unsafe { Enumeration::ref_from_raw(BNFinalizeEnumerationBuilder(self.handle)) } + unsafe { Enumeration::ref_from_raw(BNFinalizeEnumerationBuilder(self.as_raw())) } } pub fn append(&self, name: S) -> &Self { let name = name.into_bytes_with_nul(); unsafe { - BNAddEnumerationBuilderMember(self.handle, name.as_ref().as_ptr() as _); + BNAddEnumerationBuilderMember(self.as_raw(), name.as_ref().as_ptr() as _); } self } @@ -1625,7 +1626,11 @@ impl EnumerationBuilder { pub fn insert(&self, name: S, value: u64) -> &Self { let name = name.into_bytes_with_nul(); unsafe { - BNAddEnumerationBuilderMemberWithValue(self.handle, name.as_ref().as_ptr() as _, value); + BNAddEnumerationBuilderMemberWithValue( + self.as_raw(), + name.as_ref().as_ptr() as _, + value, + ); } self } @@ -1633,14 +1638,19 @@ impl EnumerationBuilder { pub fn replace(&self, id: usize, name: S, value: u64) -> &Self { let name = name.into_bytes_with_nul(); unsafe { - BNReplaceEnumerationBuilderMember(self.handle, id, name.as_ref().as_ptr() as _, value); + BNReplaceEnumerationBuilderMember( + self.as_raw(), + id, + name.as_ref().as_ptr() as _, + value, + ); } self } pub fn remove(&self, id: usize) -> &Self { unsafe { - BNRemoveEnumerationBuilderMember(self.handle, id); + BNRemoveEnumerationBuilderMember(self.as_raw(), id); } self @@ -1649,7 +1659,7 @@ impl EnumerationBuilder { pub fn members(&self) -> Vec { unsafe { let mut count = 0; - let members_raw = BNGetEnumerationBuilderMembers(self.handle, &mut count); + let members_raw = BNGetEnumerationBuilderMembers(self.as_raw(), &mut count); let members: &[BNEnumerationMember] = slice::from_raw_parts(members_raw, count); let result = (0..count) @@ -1672,16 +1682,15 @@ impl Default for EnumerationBuilder { impl From<&Enumeration> for EnumerationBuilder { fn from(enumeration: &Enumeration) -> Self { unsafe { - Self::from_raw(BNCreateEnumerationBuilderFromEnumeration( - enumeration.handle, - )) + let result = BNCreateEnumerationBuilderFromEnumeration(enumeration.handle); + Self::from_raw(NonNull::new(result).unwrap()) } } } impl Drop for EnumerationBuilder { fn drop(&mut self) { - unsafe { BNFreeEnumerationBuilder(self.handle) }; + unsafe { BNFreeEnumerationBuilder(self.as_raw()) }; } } From ed8884dc2b9e577868f634c51ac0a13844bf177c Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Wed, 29 May 2024 13:44:23 -0300 Subject: [PATCH 07/33] change `Enumeration` to the new standard --- rust/src/types.rs | 100 +++++++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 46 deletions(-) diff --git a/rust/src/types.rs b/rust/src/types.rs index df8ca304a..c7f88b4e2 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -464,13 +464,10 @@ impl TypeBuilder { } } - pub fn get_enumeration(&self) -> Result> { - let result = unsafe { BNGetTypeBuilderEnumeration(self.as_raw()) }; - if result.is_null() { - Err(()) - } else { - Ok(unsafe { Enumeration::ref_from_raw(result) }) - } + pub fn get_enumeration(&self) -> Result { + NonNull::new(unsafe { BNGetTypeBuilderEnumeration(self.as_raw()) }) + .map(|result| unsafe { Enumeration::from_raw(result) }) + .ok_or(()) } pub fn get_named_type_reference(&self) -> Result> { @@ -569,7 +566,7 @@ impl TypeBuilder { let mut fake_arch: BNArchitecture = mem::zeroed(); let result = BNCreateEnumerationTypeBuilder( &mut fake_arch, - enumeration.handle, + enumeration.as_raw(), width, &mut is_signed.into().into(), ); @@ -855,13 +852,10 @@ impl Type { } } - pub fn get_enumeration(&self) -> Result> { - let result = unsafe { BNGetTypeEnumeration(self.as_raw()) }; - if result.is_null() { - Err(()) - } else { - Ok(unsafe { Enumeration::ref_from_raw(result) }) - } + pub fn get_enumeration(&self) -> Result { + NonNull::new(unsafe { BNGetTypeEnumeration(self.as_raw()) }) + .map(|result| unsafe { Enumeration::from_raw(result) }) + .ok_or(()) } pub fn get_named_type_reference(&self) -> Result> { @@ -972,7 +966,7 @@ impl Type { let mut fake_arch: BNArchitecture = mem::zeroed(); let result = BNCreateEnumerationType( &mut fake_arch, - enumeration.handle, + enumeration.as_raw(), width, &mut is_signed.into().into(), ); @@ -1589,8 +1583,29 @@ impl EnumerationMember { pub(crate) unsafe fn from_raw(member: BNEnumerationMember) -> Self { mem::transmute(member) } + + pub(crate) unsafe fn ref_from_raw(member: &BNEnumerationMember) -> &Self { + mem::transmute(member) + } +} + +impl CoreArrayProvider for EnumerationMember { + type Raw = BNEnumerationMember; + type Context = (); + type Wrapped<'a> = &'a Self; +} + +unsafe impl CoreArrayProviderInner for EnumerationMember { + unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) { + BNFreeEnumerationMemberList(raw, count) + } + + unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> { + Self::ref_from_raw(raw) + } } +#[repr(transparent)] #[derive(PartialEq, Eq, Hash)] pub struct EnumerationBuilder { handle: NonNull, @@ -1611,8 +1626,11 @@ impl EnumerationBuilder { unsafe { &mut (*self.handle.as_ptr()) } } - pub fn finalize(&self) -> Ref { - unsafe { Enumeration::ref_from_raw(BNFinalizeEnumerationBuilder(self.as_raw())) } + pub fn finalize(&self) -> Enumeration { + unsafe { + let result = BNFinalizeEnumerationBuilder(self.as_raw()); + Enumeration::from_raw(NonNull::new(result).unwrap()) + } } pub fn append(&self, name: S) -> &Self { @@ -1682,7 +1700,7 @@ impl Default for EnumerationBuilder { impl From<&Enumeration> for EnumerationBuilder { fn from(enumeration: &Enumeration) -> Self { unsafe { - let result = BNCreateEnumerationBuilderFromEnumeration(enumeration.handle); + let result = BNCreateEnumerationBuilderFromEnumeration(enumeration.as_raw()); Self::from_raw(NonNull::new(result).unwrap()) } } @@ -1697,53 +1715,43 @@ impl Drop for EnumerationBuilder { ///////////////// // Enumeration +#[repr(transparent)] #[derive(PartialEq, Eq, Hash)] pub struct Enumeration { - pub(crate) handle: *mut BNEnumeration, + handle: NonNull, } impl Enumeration { - pub(crate) unsafe fn ref_from_raw(handle: *mut BNEnumeration) -> Ref { - debug_assert!(!handle.is_null()); - Ref::new(Self { handle }) + pub(crate) unsafe fn from_raw(handle: NonNull) -> Self { + Self { handle } + } + + pub(crate) fn as_raw(&self) -> &mut BNEnumeration { + unsafe { &mut (*self.handle.as_ptr()) } } pub fn builder() -> EnumerationBuilder { EnumerationBuilder::new() } - pub fn members(&self) -> Vec { + pub fn members(&self) -> Array { unsafe { let mut count = 0; - let members_raw = BNGetEnumerationMembers(self.handle, &mut count); - let members: &[BNEnumerationMember] = slice::from_raw_parts(members_raw, count); - - let result = (0..count) - .map(|i| EnumerationMember::from_raw(members[i])) - .collect(); - - BNFreeEnumerationMemberList(members_raw, count); - - result + let members_raw = BNGetEnumerationMembers(self.as_raw(), &mut count); + Array::new(members_raw, count, ()) } } } -unsafe impl RefCountable for Enumeration { - unsafe fn inc_ref(handle: &Self) -> Ref { - Self::ref_from_raw(BNNewEnumerationReference(handle.handle)) - } - - unsafe fn dec_ref(handle: &Self) { - BNFreeEnumeration(handle.handle); +impl Clone for Enumeration { + fn clone(&self) -> Self { + unsafe { Self::from_raw(NonNull::new(BNNewEnumerationReference(self.as_raw())).unwrap()) } } } -impl ToOwned for Enumeration { - type Owned = Ref; - - fn to_owned(&self) -> Self::Owned { - unsafe { RefCountable::inc_ref(self) } +impl Drop for Enumeration { + fn drop(&mut self) { + unsafe { BNFreeEnumeration(self.as_raw()) }; } } From ec15b1b602d62bcdd31aee84ff70f89873871e39 Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Wed, 29 May 2024 13:55:22 -0300 Subject: [PATCH 08/33] change `StructureBuilder` to the new standard --- rust/src/types.rs | 67 +++++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/rust/src/types.rs b/rust/src/types.rs index c7f88b4e2..1f7baf994 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -1760,9 +1760,10 @@ impl Drop for Enumeration { pub type StructureType = BNStructureVariant; +#[repr(transparent)] #[derive(PartialEq, Eq, Hash)] pub struct StructureBuilder { - pub(crate) handle: *mut BNStructureBuilder, + handle: NonNull, } /// ```no_run @@ -1792,25 +1793,29 @@ pub struct StructureBuilder { impl StructureBuilder { pub fn new() -> Self { Self { - handle: unsafe { BNCreateStructureBuilder() }, + handle: unsafe { NonNull::new(BNCreateStructureBuilder()).unwrap() }, } } - pub(crate) unsafe fn from_raw(handle: *mut BNStructureBuilder) -> Self { - debug_assert!(!handle.is_null()); + pub(crate) unsafe fn from_raw(handle: NonNull) -> Self { Self { handle } } + pub(crate) fn as_raw(&self) -> &mut BNStructureBuilder { + unsafe { &mut (*self.handle.as_ptr()) } + } + // Chainable terminal pub fn finalize(&self) -> Ref { - unsafe { Structure::ref_from_raw(BNFinalizeStructureBuilder(self.handle)) } + let result = unsafe { BNFinalizeStructureBuilder(self.as_raw()) }; + unsafe { Structure::ref_from_raw(result) } } // Chainable builders/setters pub fn set_width(&self, width: u64) -> &Self { unsafe { - BNSetStructureBuilderWidth(self.handle, width); + BNSetStructureBuilderWidth(self.as_raw(), width); } self @@ -1818,7 +1823,7 @@ impl StructureBuilder { pub fn set_alignment(&self, alignment: usize) -> &Self { unsafe { - BNSetStructureBuilderAlignment(self.handle, alignment); + BNSetStructureBuilderAlignment(self.as_raw(), alignment); } self @@ -1826,24 +1831,24 @@ impl StructureBuilder { pub fn set_packed(&self, packed: bool) -> &Self { unsafe { - BNSetStructureBuilderPacked(self.handle, packed); + BNSetStructureBuilderPacked(self.as_raw(), packed); } self } pub fn set_structure_type(&self, t: StructureType) -> &Self { - unsafe { BNSetStructureBuilderType(self.handle, t) }; + unsafe { BNSetStructureBuilderType(self.as_raw(), t) }; self } pub fn set_pointer_offset(&self, offset: i64) -> &Self { - unsafe { BNSetStructureBuilderPointerOffset(self.handle, offset) }; + unsafe { BNSetStructureBuilderPointerOffset(self.as_raw(), offset) }; self } pub fn set_propagates_data_var_refs(&self, does: bool) -> &Self { - unsafe { BNSetStructureBuilderPropagatesDataVariableReferences(self.handle, does) }; + unsafe { BNSetStructureBuilderPropagatesDataVariableReferences(self.as_raw(), does) }; self } @@ -1859,7 +1864,7 @@ impl StructureBuilder { unsafe { BNSetBaseStructuresForStructureBuilder( - self.handle, + self.as_raw(), bases_api.as_mut_ptr(), bases_api.len(), ) @@ -1878,7 +1883,7 @@ impl StructureBuilder { let name = name.into_bytes_with_nul(); unsafe { BNAddStructureBuilderMember( - self.handle, + self.as_raw(), &t.into().into(), name.as_ref().as_ptr() as _, access, @@ -1914,7 +1919,7 @@ impl StructureBuilder { let name = name.into_bytes_with_nul(); unsafe { BNAddStructureBuilderMemberAtOffset( - self.handle, + self.as_raw(), &t.into().into(), name.as_ref().as_ptr() as _, offset, @@ -1940,32 +1945,32 @@ impl StructureBuilder { // Getters pub fn width(&self) -> u64 { - unsafe { BNGetStructureBuilderWidth(self.handle) } + unsafe { BNGetStructureBuilderWidth(self.as_raw()) } } pub fn alignment(&self) -> usize { - unsafe { BNGetStructureBuilderAlignment(self.handle) } + unsafe { BNGetStructureBuilderAlignment(self.as_raw()) } } pub fn packed(&self) -> bool { - unsafe { BNIsStructureBuilderPacked(self.handle) } + unsafe { BNIsStructureBuilderPacked(self.as_raw()) } } pub fn structure_type(&self) -> StructureType { - unsafe { BNGetStructureBuilderType(self.handle) } + unsafe { BNGetStructureBuilderType(self.as_raw()) } } pub fn pointer_offset(&self) -> i64 { - unsafe { BNGetStructureBuilderPointerOffset(self.handle) } + unsafe { BNGetStructureBuilderPointerOffset(self.as_raw()) } } pub fn propagates_data_var_refs(&self) -> bool { - unsafe { BNStructureBuilderPropagatesDataVariableReferences(self.handle) } + unsafe { BNStructureBuilderPropagatesDataVariableReferences(self.as_raw()) } } pub fn base_structures(&self) -> Result> { let mut count = 0usize; - let bases = unsafe { BNGetBaseStructuresForStructureBuilder(self.handle, &mut count) }; + let bases = unsafe { BNGetBaseStructuresForStructureBuilder(self.as_raw(), &mut count) }; if bases.is_null() { Err(()) } else { @@ -1986,7 +1991,7 @@ impl StructureBuilder { pub fn members(&self) -> Array { let mut count = 0; - let members_raw = unsafe { BNGetStructureBuilderMembers(self.handle, &mut count) }; + let members_raw = unsafe { BNGetStructureBuilderMembers(self.as_raw(), &mut count) }; unsafe { Array::new(members_raw, count, ()) } } @@ -2021,7 +2026,7 @@ impl StructureBuilder { } pub fn remove(&self, index: usize) { - unsafe { BNRemoveStructureBuilderMember(self.handle, index) } + unsafe { BNRemoveStructureBuilderMember(self.as_raw(), index) } } pub fn replace(&self, index: usize, type_: Conf<&Type>, name: &str, overwrite: bool) { @@ -2033,14 +2038,15 @@ impl StructureBuilder { confidence: type_.confidence, }; unsafe { - BNReplaceStructureBuilderMember(self.handle, index, &raw_type_, name_ptr, overwrite) + BNReplaceStructureBuilderMember(self.as_raw(), index, &raw_type_, name_ptr, overwrite) } } } impl From<&Structure> for StructureBuilder { fn from(structure: &Structure) -> StructureBuilder { - unsafe { Self::from_raw(BNCreateStructureBuilderFromStructure(structure.handle)) } + let result = unsafe { BNCreateStructureBuilderFromStructure(structure.handle) }; + unsafe { Self::from_raw(NonNull::new(result).unwrap()) } } } @@ -2060,9 +2066,18 @@ impl Debug for StructureBuilder { } } +impl Clone for StructureBuilder { + fn clone(&self) -> Self { + let result = unsafe { BNDuplicateStructureBuilder(self.as_raw()) }; + Self { + handle: NonNull::new(result).unwrap(), + } + } +} + impl Drop for StructureBuilder { fn drop(&mut self) { - unsafe { BNFreeStructureBuilder(self.handle) }; + unsafe { BNFreeStructureBuilder(self.as_raw()) }; } } From 1e43870bc09ba87bfba3b3cdf73ec1deec79470b Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Wed, 29 May 2024 14:06:08 -0300 Subject: [PATCH 09/33] change `Structure` to the new standard --- rust/src/types.rs | 69 +++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 41 deletions(-) diff --git a/rust/src/types.rs b/rust/src/types.rs index 1f7baf994..eade0eb9e 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -455,13 +455,10 @@ impl TypeBuilder { unsafe { BNIsTypeBuilderPure(self.as_raw()).into() } } - pub fn get_structure(&self) -> Result> { - let result = unsafe { BNGetTypeBuilderStructure(self.as_raw()) }; - if result.is_null() { - Err(()) - } else { - Ok(unsafe { Structure::ref_from_raw(result) }) - } + pub fn get_structure(&self) -> Result { + NonNull::new(unsafe { BNGetTypeBuilderStructure(self.as_raw()) }) + .map(|result| unsafe { Structure::from_raw(result) }) + .ok_or(()) } pub fn get_enumeration(&self) -> Result { @@ -577,7 +574,7 @@ impl TypeBuilder { pub fn structure(structure_type: &Structure) -> Self { unsafe { Self::from_raw( - NonNull::new(BNCreateStructureTypeBuilder(structure_type.handle)).unwrap(), + NonNull::new(BNCreateStructureTypeBuilder(structure_type.as_raw())).unwrap(), ) } } @@ -843,13 +840,10 @@ impl Type { unsafe { BNIsTypePure(self.as_raw()).into() } } - pub fn get_structure(&self) -> Result> { - let result = unsafe { BNGetTypeStructure(self.as_raw()) }; - if result.is_null() { - Err(()) - } else { - Ok(unsafe { Structure::ref_from_raw(result) }) - } + pub fn get_structure(&self) -> Result { + NonNull::new(unsafe { BNGetTypeStructure(self.as_raw()) }) + .map(|result| unsafe { Structure::from_raw(result) }) + .ok_or(()) } pub fn get_enumeration(&self) -> Result { @@ -975,7 +969,7 @@ impl Type { } pub fn structure(structure: &Structure) -> Self { - unsafe { Self::from_raw(NonNull::new(BNCreateStructureType(structure.handle)).unwrap()) } + unsafe { Self::from_raw(NonNull::new(BNCreateStructureType(structure.as_raw())).unwrap()) } } pub fn named_type(type_reference: &NamedTypeReference) -> Self { @@ -1806,9 +1800,9 @@ impl StructureBuilder { } // Chainable terminal - pub fn finalize(&self) -> Ref { + pub fn finalize(&self) -> Structure { let result = unsafe { BNFinalizeStructureBuilder(self.as_raw()) }; - unsafe { Structure::ref_from_raw(result) } + unsafe { Structure::from_raw(NonNull::new(result).unwrap()) } } // Chainable builders/setters @@ -2045,7 +2039,7 @@ impl StructureBuilder { impl From<&Structure> for StructureBuilder { fn from(structure: &Structure) -> StructureBuilder { - let result = unsafe { BNCreateStructureBuilderFromStructure(structure.handle) }; + let result = unsafe { BNCreateStructureBuilderFromStructure(structure.as_raw()) }; unsafe { Self::from_raw(NonNull::new(result).unwrap()) } } } @@ -2090,20 +2084,19 @@ impl Default for StructureBuilder { /////////////// // Structure +#[repr(transparent)] #[derive(PartialEq, Eq, Hash)] pub struct Structure { - pub(crate) handle: *mut BNStructure, + handle: NonNull, } impl Structure { - unsafe fn from_raw(handle: *mut BNStructure) -> Self { - debug_assert!(!handle.is_null()); + pub(crate) unsafe fn from_raw(handle: NonNull) -> Self { Self { handle } } - pub(crate) unsafe fn ref_from_raw(handle: *mut BNStructure) -> Ref { - debug_assert!(!handle.is_null()); - Ref::new(Self { handle }) + pub(crate) fn as_raw(&self) -> &mut BNStructure { + unsafe { &mut (*self.handle.as_ptr()) } } pub fn builder() -> StructureBuilder { @@ -2111,18 +2104,18 @@ impl Structure { } pub fn width(&self) -> u64 { - unsafe { BNGetStructureWidth(self.handle) } + unsafe { BNGetStructureWidth(self.as_raw()) } } pub fn structure_type(&self) -> StructureType { - unsafe { BNGetStructureType(self.handle) } + unsafe { BNGetStructureType(self.as_raw()) } } pub fn members(&self) -> Result> { unsafe { let mut count = 0; let members_raw: *mut BNStructureMember = - BNGetStructureMembers(self.handle, &mut count); + BNGetStructureMembers(self.as_raw(), &mut count); if members_raw.is_null() { return Err(()); } @@ -2140,7 +2133,7 @@ impl Structure { pub fn base_structures(&self) -> Result> { let mut count = 0usize; - let bases = unsafe { BNGetBaseStructuresForStructure(self.handle, &mut count) }; + let bases = unsafe { BNGetBaseStructuresForStructure(self.as_raw(), &mut count) }; if bases.is_null() { Err(()) } else { @@ -2174,21 +2167,15 @@ impl Debug for Structure { } } -unsafe impl RefCountable for Structure { - unsafe fn inc_ref(handle: &Self) -> Ref { - Ref::new(Self::from_raw(BNNewStructureReference(handle.handle))) - } - - unsafe fn dec_ref(handle: &Self) { - BNFreeStructure(handle.handle); +impl Clone for Structure { + fn clone(&self) -> Self { + unsafe { Self::from_raw(NonNull::new(BNNewStructureReference(self.as_raw())).unwrap()) } } } -impl ToOwned for Structure { - type Owned = Ref; - - fn to_owned(&self) -> Self::Owned { - unsafe { RefCountable::inc_ref(self) } +impl Drop for Structure { + fn drop(&mut self) { + unsafe { BNFreeStructure(self.as_raw()) } } } From 865ae406c660c51d24a85ecf4d418f530138a624 Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Wed, 29 May 2024 14:14:39 -0300 Subject: [PATCH 10/33] change `StructureMember` to the new standard --- rust/src/types.rs | 60 ++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/rust/src/types.rs b/rust/src/types.rs index eade0eb9e..0d2fdc383 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -1990,7 +1990,9 @@ impl StructureBuilder { } pub fn index_by_name(&self, name: &str) -> Option { - self.members().iter().position(|member| member.name == name) + self.members() + .iter() + .position(|member| member.name() == name) } pub fn index_by_offset(&self, offset: u64) -> Option { @@ -2010,7 +2012,7 @@ impl StructureBuilder { pub fn add_members<'a>(&self, members: impl IntoIterator) { for member in members { - self.append(&member.ty, &member.name, member.access, member.scope); + self.append(&member.ty, member.name(), member.access, member.scope); } } @@ -2111,7 +2113,7 @@ impl Structure { unsafe { BNGetStructureType(self.as_raw()) } } - pub fn members(&self) -> Result> { + pub fn members(&self) -> Result> { unsafe { let mut count = 0; let members_raw: *mut BNStructureMember = @@ -2119,15 +2121,7 @@ impl Structure { if members_raw.is_null() { return Err(()); } - let members = slice::from_raw_parts(members_raw, count); - - let result = (0..count) - .map(|i| StructureMember::ref_from_raw(members[i])) - .collect(); - - BNFreeStructureMemberList(members_raw, count); - - Ok(result) + Ok(Array::new(members_raw, count, ())) } } @@ -2159,7 +2153,7 @@ impl Debug for Structure { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "Structure {{")?; if let Ok(members) = self.members() { - for member in members { + for member in &members { write!(f, " {:?}", member)?; } } @@ -2179,50 +2173,52 @@ impl Drop for Structure { } } +#[repr(C)] #[derive(Debug, Clone)] pub struct StructureMember { - pub ty: Conf, - pub name: String, + ty: Type, + name: BnString, pub offset: u64, + type_confidence: u8, pub access: MemberAccess, pub scope: MemberScope, } impl StructureMember { - pub fn new( + pub fn new( ty: Conf, - name: String, + name: S, offset: u64, access: MemberAccess, scope: MemberScope, ) -> Self { Self { - ty, - name, + ty: ty.contents, + name: BnString::new(name), offset, + type_confidence: ty.confidence, access, scope, } } - pub(crate) unsafe fn ref_from_raw(handle: BNStructureMember) -> Self { - Self { - ty: Conf::new( - Type::ref_from_raw(&handle.type_).clone(), - handle.typeConfidence, - ), - name: CStr::from_ptr(handle.name).to_string_lossy().to_string(), - offset: handle.offset, - access: handle.access, - scope: handle.scope, - } + pub(crate) unsafe fn ref_from_raw(handle: &BNStructureMember) -> &Self { + mem::transmute(handle) + } + + pub fn ty(&self) -> Conf<&Type> { + Conf::new(&self.ty, self.type_confidence) + } + + pub fn name(&self) -> &str { + self.name.as_str() } } impl CoreArrayProvider for StructureMember { type Raw = BNStructureMember; type Context = (); - type Wrapped<'a> = Guard<'a, StructureMember>; + type Wrapped<'a> = &'a StructureMember; } unsafe impl CoreArrayProviderInner for StructureMember { @@ -2230,7 +2226,7 @@ unsafe impl CoreArrayProviderInner for StructureMember { BNFreeStructureMemberList(raw, count) } unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> { - Guard::new(StructureMember::ref_from_raw(*raw), &()) + StructureMember::ref_from_raw(raw) } } From a019f2fe0339d6df83dee56f90f437dc4bba0fe1 Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Wed, 29 May 2024 14:24:18 -0300 Subject: [PATCH 11/33] convert Vec into Array --- rust/src/types.rs | 78 +++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 53 deletions(-) diff --git a/rust/src/types.rs b/rust/src/types.rs index 0d2fdc383..3bf23c067 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -422,23 +422,14 @@ impl TypeBuilder { } } - pub fn parameters(&self) -> Result> { + pub fn parameters(&self) -> Result> { unsafe { let mut count = 0; let parameters_raw = BNGetTypeBuilderParameters(self.as_raw(), &mut count); if parameters_raw.is_null() { Err(()) } else { - let parameters: &[BNFunctionParameter] = - slice::from_raw_parts(parameters_raw, count); - - let result = (0..count) - .map(|i| FunctionParameter::from_raw(parameters[i])) - .collect(); - - BNFreeTypeParameterList(parameters_raw, count); - - Ok(result) + Ok(Array::new(parameters_raw, count, ())) } } } @@ -806,7 +797,7 @@ impl Type { } } - pub fn parameters(&self) -> Result> { + pub fn parameters(&self) -> Result> { unsafe { let mut count = 0; let parameters_raw: *mut BNFunctionParameter = @@ -814,16 +805,7 @@ impl Type { if parameters_raw.is_null() { Err(()) } else { - let parameters: &[BNFunctionParameter] = - slice::from_raw_parts(parameters_raw, count); - - let result = (0..count) - .map(|i| FunctionParameter::from_raw(parameters[i])) - .collect(); - - BNFreeTypeParameterList(parameters_raw, count); - - Ok(result) + Ok(Array::new(parameters_raw, count, ())) } } } @@ -1319,23 +1301,9 @@ impl FunctionParameter { } } - pub(crate) unsafe fn from_raw(member: BNFunctionParameter) -> Self { - let name = NonNull::new(member.name).map(|name| unsafe { BnString::from_raw(name) }); - - let location = if member.defaultLocation { - // dummy value - Variable::new(BNVariableSourceType::StackVariableSourceType, 0, 0) - } else { - unsafe { Variable::from_raw(member.location) } - }; - - Self { - t: unsafe { Type::from_raw(NonNull::new(BNNewTypeReference(member.type_)).unwrap()) }, - type_confidence: member.typeConfidence, - name, - default_location: member.defaultLocation, - location, - } + pub(crate) unsafe fn ref_from_raw(handle: &BNFunctionParameter) -> &Self { + assert!(!handle.type_.is_null()); + mem::transmute(handle) } pub fn location(&self) -> Option { @@ -1365,6 +1333,22 @@ impl FunctionParameter { } } +impl CoreArrayProvider for FunctionParameter { + type Raw = BNFunctionParameter; + type Context = (); + type Wrapped<'a> = &'a Self; +} + +unsafe impl CoreArrayProviderInner for FunctionParameter { + unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) { + BNFreeTypeParameterList(raw, count) + } + + unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> { + Self::ref_from_raw(raw) + } +} + ////////////// // Variable @@ -1574,10 +1558,6 @@ impl EnumerationMember { } } - pub(crate) unsafe fn from_raw(member: BNEnumerationMember) -> Self { - mem::transmute(member) - } - pub(crate) unsafe fn ref_from_raw(member: &BNEnumerationMember) -> &Self { mem::transmute(member) } @@ -1668,19 +1648,11 @@ impl EnumerationBuilder { self } - pub fn members(&self) -> Vec { + pub fn members(&self) -> Array { unsafe { let mut count = 0; let members_raw = BNGetEnumerationBuilderMembers(self.as_raw(), &mut count); - let members: &[BNEnumerationMember] = slice::from_raw_parts(members_raw, count); - - let result = (0..count) - .map(|i| EnumerationMember::from_raw(members[i])) - .collect(); - - BNFreeEnumerationMemberList(members_raw, count); - - result + Array::new(members_raw, count, ()) } } } From d44c3edbcbff05830775dfc3d5435d38ccd4b232 Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Wed, 29 May 2024 14:49:36 -0300 Subject: [PATCH 12/33] change `NamedTypeReference` to the new standard --- rust/src/binaryview.rs | 2 +- rust/src/types.rs | 115 +++++++++++++++++++---------------------- 2 files changed, 55 insertions(+), 62 deletions(-) diff --git a/rust/src/binaryview.rs b/rust/src/binaryview.rs index c03a9891c..c0fef620c 100644 --- a/rust/src/binaryview.rs +++ b/rust/src/binaryview.rs @@ -733,7 +733,7 @@ pub trait BinaryViewExt: BinaryViewBase { fn get_type_by_ref(&self, ref_: &NamedTypeReference) -> Option { unsafe { - let type_handle = BNGetAnalysisTypeByRef(self.as_ref().handle, ref_.handle); + let type_handle = BNGetAnalysisTypeByRef(self.as_ref().handle, ref_.as_raw()); if type_handle.is_null() { return None; } diff --git a/rust/src/types.rs b/rust/src/types.rs index 3bf23c067..9799b27e0 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -458,13 +458,10 @@ impl TypeBuilder { .ok_or(()) } - pub fn get_named_type_reference(&self) -> Result> { - let result = unsafe { BNGetTypeBuilderNamedTypeReference(self.as_raw()) }; - if result.is_null() { - Err(()) - } else { - Ok(unsafe { NamedTypeReference::ref_from_raw(result) }) - } + pub fn get_named_type_reference(&self) -> Result { + NonNull::new(unsafe { BNGetTypeBuilderNamedTypeReference(self.as_raw()) }) + .map(|result| unsafe { NamedTypeReference::from_raw(result) }) + .ok_or(()) } pub fn count(&self) -> u64 { @@ -575,7 +572,7 @@ impl TypeBuilder { let mut is_volatile = Conf::new(false, min_confidence()).into(); unsafe { let result = BNCreateNamedTypeReferenceBuilder( - type_reference.handle, + type_reference.as_raw(), 0, 1, &mut is_const, @@ -834,13 +831,10 @@ impl Type { .ok_or(()) } - pub fn get_named_type_reference(&self) -> Result> { - let result = unsafe { BNGetTypeNamedTypeReference(self.as_raw()) }; - if result.is_null() { - Err(()) - } else { - Ok(unsafe { NamedTypeReference::ref_from_raw(result) }) - } + pub fn get_named_type_reference(&self) -> Result { + NonNull::new(unsafe { BNGetTypeNamedTypeReference(self.as_raw()) }) + .map(|result| unsafe { NamedTypeReference::from_raw(result) }) + .ok_or(()) } pub fn count(&self) -> u64 { @@ -855,13 +849,10 @@ impl Type { unsafe { BNGetTypeStackAdjustment(self.as_raw()).into() } } - pub fn registered_name(&self) -> Result> { - let result = unsafe { BNGetRegisteredTypeName(self.as_raw()) }; - if result.is_null() { - Err(()) - } else { - Ok(unsafe { NamedTypeReference::ref_from_raw(result) }) - } + pub fn registered_name(&self) -> Result { + NonNull::new(unsafe { BNGetRegisteredTypeName(self.as_raw()) }) + .map(|result| unsafe { NamedTypeReference::from_raw(result) }) + .ok_or(()) } // TODO : This and properties @@ -959,7 +950,7 @@ impl Type { let mut is_volatile = Conf::new(false, min_confidence()).into(); unsafe { let result = BNCreateNamedTypeReference( - type_reference.handle, + type_reference.as_raw(), 0, 1, &mut is_const, @@ -1822,7 +1813,7 @@ impl StructureBuilder { let mut bases_api = vec![]; for base in bases { bases_api.push(BNBaseStructure { - type_: base.ty.handle, + type_: base.ty.handle.as_ptr(), offset: base.offset, width: base.width, }); @@ -2204,7 +2195,7 @@ unsafe impl CoreArrayProviderInner for StructureMember { #[derive(Debug, Clone)] pub struct InheritedStructureMember { - pub base: Ref, + pub base: NamedTypeReference, pub base_offset: u64, pub member: StructureMember, pub member_index: usize, @@ -2212,7 +2203,7 @@ pub struct InheritedStructureMember { impl InheritedStructureMember { pub fn new( - base: Ref, + base: NamedTypeReference, base_offset: u64, member: StructureMember, member_index: usize, @@ -2237,19 +2228,19 @@ impl InheritedStructureMember { #[derive(Debug, Clone)] pub struct BaseStructure { - pub ty: Ref, + pub ty: NamedTypeReference, pub offset: u64, pub width: u64, } impl BaseStructure { - pub fn new(ty: Ref, offset: u64, width: u64) -> Self { + pub fn new(ty: NamedTypeReference, offset: u64, width: u64) -> Self { Self { ty, offset, width } } pub(crate) unsafe fn from_raw(handle: BNBaseStructure) -> Self { Self { - ty: RefCountable::inc_ref(&NamedTypeReference::from_raw(handle.type_)), + ty: NamedTypeReference::from_raw(NonNull::new(handle.type_).unwrap()), offset: handle.offset, width: handle.width, } @@ -2259,21 +2250,19 @@ impl BaseStructure { //////////////////////// // NamedTypeReference +#[repr(transparent)] #[derive(PartialEq, Eq, Hash)] pub struct NamedTypeReference { - pub(crate) handle: *mut BNNamedTypeReference, + handle: NonNull, } impl NamedTypeReference { - pub(crate) unsafe fn from_raw(handle: *mut BNNamedTypeReference) -> Self { - debug_assert!(!handle.is_null()); - - Self { handle } + pub(crate) unsafe fn from_raw(handle: NonNull) -> Self { + mem::transmute(handle) } - pub(crate) unsafe fn ref_from_raw(handle: *mut BNNamedTypeReference) -> Ref { - debug_assert!(!handle.is_null()); - Ref::new(Self { handle }) + pub(crate) fn as_raw(&self) -> &mut BNNamedTypeReference { + unsafe { &mut (*self.handle.as_ptr()) } } /// Create an NTR to a type that did not come directly from a BinaryView's types list. @@ -2281,11 +2270,14 @@ impl NamedTypeReference { /// You should not assign type ids yourself, that is the responsibility of the BinaryView /// implementation after your types have been added. Just make sure the names match up and /// the core will do the id stuff for you. - pub fn new(type_class: NamedTypeReferenceClass, mut name: QualifiedName) -> Ref { + pub fn new(type_class: NamedTypeReferenceClass, name: &QualifiedName) -> Self { unsafe { - RefCountable::inc_ref(&Self { - handle: BNCreateNamedType(type_class, ptr::null() as *const _, &mut name.0), - }) + let result = BNCreateNamedType( + type_class, + ptr::null(), + &name.0 as *const _ as *mut BNQualifiedName, + ); + Self::from_raw(NonNull::new(result).unwrap()) } } @@ -2297,28 +2289,31 @@ impl NamedTypeReference { pub fn new_with_id( type_class: NamedTypeReferenceClass, type_id: S, - mut name: QualifiedName, - ) -> Ref { + name: &QualifiedName, + ) -> Self { let type_id = type_id.into_bytes_with_nul(); unsafe { - RefCountable::inc_ref(&Self { - handle: BNCreateNamedType(type_class, type_id.as_ref().as_ptr() as _, &mut name.0), - }) + let result = BNCreateNamedType( + type_class, + type_id.as_ref().as_ptr() as _, + &name.0 as *const _ as *mut BNQualifiedName, + ); + Self::from_raw(NonNull::new(result).unwrap()) } } pub fn name(&self) -> QualifiedName { - let named_ref: BNQualifiedName = unsafe { BNGetTypeReferenceName(self.handle) }; + let named_ref: BNQualifiedName = unsafe { BNGetTypeReferenceName(self.as_raw()) }; QualifiedName(named_ref) } pub fn id(&self) -> BnString { - unsafe { BnString::from_raw(NonNull::new(BNGetTypeReferenceId(self.handle)).unwrap()) } + unsafe { BnString::from_raw(NonNull::new(BNGetTypeReferenceId(self.as_raw())).unwrap()) } } pub fn class(&self) -> NamedTypeReferenceClass { - unsafe { BNGetTypeReferenceClass(self.handle) } + unsafe { BNGetTypeReferenceClass(self.as_raw()) } } fn target_helper(&self, bv: &BinaryView, visited: &mut HashSet) -> Option { @@ -2348,21 +2343,15 @@ impl NamedTypeReference { } } -impl ToOwned for NamedTypeReference { - type Owned = Ref; - - fn to_owned(&self) -> Self::Owned { - unsafe { RefCountable::inc_ref(self) } +impl Clone for NamedTypeReference { + fn clone(&self) -> Self { + unsafe { Self::from_raw(NonNull::new(BNNewNamedTypeReference(self.as_raw())).unwrap()) } } } -unsafe impl RefCountable for NamedTypeReference { - unsafe fn inc_ref(handle: &Self) -> Ref { - Self::ref_from_raw(BNNewNamedTypeReference(handle.handle)) - } - - unsafe fn dec_ref(handle: &Self) { - BNFreeNamedTypeReference(handle.handle) +impl Drop for NamedTypeReference { + fn drop(&mut self) { + unsafe { BNFreeNamedTypeReference(self.as_raw()) } } } @@ -3785,4 +3774,8 @@ mod test { let type_built = type_builder.finalize(); assert_eq!(type_built, expected_type); } + + // TODO NamedTypeReference::new, NamedTypeReference::new_with_id was + // previously leaking memory, probably because the name received a ownership + // and didn't clone it, please verify the fix } From bd54936bad8a5b347aa1d68047fe2244611894bd Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Wed, 29 May 2024 14:54:25 -0300 Subject: [PATCH 13/33] change `BaseStructure` to the new standard --- rust/src/types.rs | 55 ++++++++++++++++++++--------------------------- 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/rust/src/types.rs b/rust/src/types.rs index 9799b27e0..1fb46452e 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -1925,24 +1925,13 @@ impl StructureBuilder { unsafe { BNStructureBuilderPropagatesDataVariableReferences(self.as_raw()) } } - pub fn base_structures(&self) -> Result> { + pub fn base_structures(&self) -> Result> { let mut count = 0usize; let bases = unsafe { BNGetBaseStructuresForStructureBuilder(self.as_raw(), &mut count) }; if bases.is_null() { Err(()) } else { - let bases_slice = unsafe { slice::from_raw_parts_mut(bases, count) }; - - let result = bases_slice - .iter() - .map(|base| unsafe { BaseStructure::from_raw(*base) }) - .collect::>(); - - unsafe { - BNFreeBaseStructureList(bases, count); - } - - Ok(result) + Ok(unsafe { Array::new(bases, count, ()) }) } } @@ -2088,24 +2077,13 @@ impl Structure { } } - pub fn base_structures(&self) -> Result> { + pub fn base_structures(&self) -> Result> { let mut count = 0usize; let bases = unsafe { BNGetBaseStructuresForStructure(self.as_raw(), &mut count) }; if bases.is_null() { Err(()) } else { - let bases_slice = unsafe { slice::from_raw_parts_mut(bases, count) }; - - let result = bases_slice - .iter() - .map(|base| unsafe { BaseStructure::from_raw(*base) }) - .collect::>(); - - unsafe { - BNFreeBaseStructureList(bases, count); - } - - Ok(result) + Ok(unsafe { Array::new(bases, count, ()) }) } } @@ -2226,6 +2204,7 @@ impl InheritedStructureMember { // } } +#[repr(C)] #[derive(Debug, Clone)] pub struct BaseStructure { pub ty: NamedTypeReference, @@ -2238,12 +2217,24 @@ impl BaseStructure { Self { ty, offset, width } } - pub(crate) unsafe fn from_raw(handle: BNBaseStructure) -> Self { - Self { - ty: NamedTypeReference::from_raw(NonNull::new(handle.type_).unwrap()), - offset: handle.offset, - width: handle.width, - } + pub(crate) unsafe fn ref_from_raw(handle: &BNBaseStructure) -> &Self { + mem::transmute(handle) + } +} + +impl CoreArrayProvider for BaseStructure { + type Raw = BNBaseStructure; + type Context = (); + type Wrapped<'a> = &'a Self; +} + +unsafe impl CoreArrayProviderInner for BaseStructure { + unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) { + BNFreeBaseStructureList(raw, count) + } + + unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> { + Self::ref_from_raw(raw) } } From f5ab5ea12e6be5f29a9ff81549de1d270b4bc93e Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Wed, 29 May 2024 15:00:13 -0300 Subject: [PATCH 14/33] change `QualifiedName` to the new standard --- rust/src/types.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rust/src/types.rs b/rust/src/types.rs index 1fb46452e..6e1ce554c 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -2359,6 +2359,10 @@ impl Debug for NamedTypeReference { pub struct QualifiedName(pub(crate) BNQualifiedName); impl QualifiedName { + pub(crate) unsafe fn ref_from_raw(handle: &BNQualifiedName) -> &Self { + mem::transmute(handle) + } + // TODO : I think this is bad pub fn string(&self) -> String { unsafe { @@ -2481,7 +2485,7 @@ unsafe impl CoreArrayProviderInner for QualifiedName { BNFreeTypeNameList(raw, count); } unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> { - mem::transmute(raw) + QualifiedName::ref_from_raw(raw) } } From 073de861025a0ed4609fac4375a3ebb6d58ba0ca Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Wed, 29 May 2024 15:24:21 -0300 Subject: [PATCH 15/33] change `QualifiedNameAndType` to the new standard --- rust/src/binaryview.rs | 16 ++++++----- rust/src/function.rs | 8 +++--- rust/src/platform.rs | 6 ++--- rust/src/templatesimplifier.rs | 2 +- rust/src/types.rs | 49 ++++++++++++++++++++++++++-------- 5 files changed, 55 insertions(+), 26 deletions(-) diff --git a/rust/src/binaryview.rs b/rust/src/binaryview.rs index c0fef620c..5f5d3c7d1 100644 --- a/rust/src/binaryview.rs +++ b/rust/src/binaryview.rs @@ -583,19 +583,21 @@ pub trait BinaryViewExt: BinaryViewBase { ) -> QualifiedName { let mut qualified_name = QualifiedName::from(name); let source_str = source.into_bytes_with_nul(); - let name_handle = unsafe { - let id_str = BNGenerateAutoTypeId( + let id_str = unsafe { + BNGenerateAutoTypeId( source_str.as_ref().as_ptr() as *const _, - &mut qualified_name.0, - ); + qualified_name.as_raw_mut(), + ) + }; + let name_handle = unsafe { BNDefineAnalysisType( self.as_ref().handle, id_str, - &mut qualified_name.0, + qualified_name.as_raw_mut(), type_obj.as_raw(), ) }; - QualifiedName(name_handle) + unsafe { QualifiedName::from_raw(name_handle) } } fn define_user_type(&self, name: S, type_obj: &Type) { @@ -603,7 +605,7 @@ pub trait BinaryViewExt: BinaryViewBase { unsafe { BNDefineUserAnalysisType( self.as_ref().handle, - &mut qualified_name.0, + qualified_name.as_raw_mut(), type_obj.as_raw(), ) } diff --git a/rust/src/function.rs b/rust/src/function.rs index d4bc688d7..29edb15ee 100644 --- a/rust/src/function.rs +++ b/rust/src/function.rs @@ -1104,7 +1104,7 @@ impl Function { arch: Option, ) { let arch = arch.unwrap_or_else(|| self.arch()); - let name_ptr = &name.0 as *const BNQualifiedName as *mut _; + let name_ptr = name.as_raw() as *const BNQualifiedName as *mut BNQualifiedName; unsafe { BNAddUserTypeReference(self.handle, arch.0, from_addr, name_ptr) } } @@ -1129,7 +1129,7 @@ impl Function { arch: Option, ) { let arch = arch.unwrap_or_else(|| self.arch()); - let name_ptr = &name.0 as *const BNQualifiedName as *mut _; + let name_ptr = name.as_raw() as *const BNQualifiedName as *mut BNQualifiedName; unsafe { BNRemoveUserTypeReference(self.handle, arch.0, from_addr, name_ptr) } } @@ -1160,7 +1160,7 @@ impl Function { ) { let size = size.unwrap_or(0); let arch = arch.unwrap_or_else(|| self.arch()); - let name_ptr = &name.0 as *const _ as *mut _; + let name_ptr = name.as_raw() as *const BNQualifiedName as *mut BNQualifiedName; unsafe { BNAddUserTypeFieldReference(self.handle, arch.0, from_addr, name_ptr, offset, size) } @@ -1192,7 +1192,7 @@ impl Function { ) { let size = size.unwrap_or(0); let arch = arch.unwrap_or_else(|| self.arch()); - let name_ptr = &name.0 as *const _ as *mut _; + let name_ptr = name.as_raw() as *const BNQualifiedName as *mut BNQualifiedName; unsafe { BNRemoveUserTypeFieldReference(self.handle, arch.0, from_addr, name_ptr, offset, size) } diff --git a/rust/src/platform.rs b/rust/src/platform.rs index 1bc505986..ccad41a27 100644 --- a/rust/src/platform.rs +++ b/rust/src/platform.rs @@ -320,7 +320,7 @@ impl TypeParser for Platform { } for i in slice::from_raw_parts(result.types, result.typeCount) { - let name = QualifiedName(i.name); + let name = QualifiedName::from_raw(i.name); type_parser_result.types.insert( name.string(), Type::from_raw(ptr::NonNull::new(i.type_).unwrap()), @@ -328,7 +328,7 @@ impl TypeParser for Platform { } for i in slice::from_raw_parts(result.functions, result.functionCount) { - let name = QualifiedName(i.name); + let name = QualifiedName::from_raw(i.name); type_parser_result.functions.insert( name.string(), Type::from_raw(ptr::NonNull::new(i.type_).unwrap()), @@ -336,7 +336,7 @@ impl TypeParser for Platform { } for i in slice::from_raw_parts(result.variables, result.variableCount) { - let name = QualifiedName(i.name); + let name = QualifiedName::from_raw(i.name); type_parser_result.variables.insert( name.string(), Type::from_raw(ptr::NonNull::new(i.type_).unwrap()), diff --git a/rust/src/templatesimplifier.rs b/rust/src/templatesimplifier.rs index 2c2e00c13..fa4f48a79 100644 --- a/rust/src/templatesimplifier.rs +++ b/rust/src/templatesimplifier.rs @@ -15,7 +15,7 @@ pub fn simplify_str_to_str(input: S) -> BnString { pub fn simplify_str_to_fqn(input: S, simplify: bool) -> QualifiedName { let name = input.into_bytes_with_nul(); unsafe { - QualifiedName(BNRustSimplifyStrToFQN( + QualifiedName::from_raw(BNRustSimplifyStrToFQN( name.as_ref().as_ptr() as *mut _, simplify, )) diff --git a/rust/src/types.rs b/rust/src/types.rs index 6e1ce554c..6a2827e52 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -2355,14 +2355,26 @@ impl Debug for NamedTypeReference { /////////////////// // QualifiedName -#[repr(transparent)] -pub struct QualifiedName(pub(crate) BNQualifiedName); +#[repr(C)] +pub struct QualifiedName(BNQualifiedName); impl QualifiedName { + pub(crate) unsafe fn from_raw(handle: BNQualifiedName) -> Self { + mem::transmute(handle) + } + pub(crate) unsafe fn ref_from_raw(handle: &BNQualifiedName) -> &Self { mem::transmute(handle) } + pub(crate) fn as_raw(&self) -> &BNQualifiedName { + &self.0 + } + + pub(crate) fn as_raw_mut(&mut self) -> &mut BNQualifiedName { + &mut self.0 + } + // TODO : I think this is bad pub fn string(&self) -> String { unsafe { @@ -2492,24 +2504,35 @@ unsafe impl CoreArrayProviderInner for QualifiedName { ////////////////////////// // QualifiedNameAndType -#[repr(transparent)] -pub struct QualifiedNameAndType(pub(crate) BNQualifiedNameAndType); +#[repr(C)] +#[derive(Debug, Clone)] +pub struct QualifiedNameAndType { + // Drop is done by BNFreeQualifiedNameAndType + name: ManuallyDrop, + type_: ManuallyDrop, +} impl QualifiedNameAndType { + pub(crate) unsafe fn ref_from_raw(handle: &BNQualifiedNameAndType) -> &QualifiedNameAndType { + mem::transmute(handle) + } + + pub(crate) fn as_raw(&mut self) -> &mut BNQualifiedNameAndType { + unsafe { mem::transmute(self) } + } + pub fn name(&self) -> &QualifiedName { - unsafe { mem::transmute(&self.0.name) } + &self.name } - pub fn type_object(&self) -> Guard { - unsafe { Guard::new(Type::from_raw(NonNull::new(self.0.type_).unwrap()), self) } + pub fn type_object(&self) -> &Type { + &self.type_ } } impl Drop for QualifiedNameAndType { fn drop(&mut self) { - unsafe { - BNFreeQualifiedNameAndType(&mut self.0); - } + unsafe { BNFreeQualifiedNameAndType(self.as_raw()) }; } } @@ -2522,8 +2545,9 @@ unsafe impl CoreArrayProviderInner for QualifiedNameAndType { unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) { BNFreeTypeAndNameList(raw, count); } + unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> { - mem::transmute(raw) + Self::ref_from_raw(raw) } } @@ -3773,4 +3797,7 @@ mod test { // TODO NamedTypeReference::new, NamedTypeReference::new_with_id was // previously leaking memory, probably because the name received a ownership // and didn't clone it, please verify the fix + + // TODO ::parse_types_from_source forgot to call + // BNFreeTypeParserResult, leaking the result } From 7af09f995f6bee32dceeac5a9fefb7788cc86bbd Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Wed, 29 May 2024 16:02:05 -0300 Subject: [PATCH 16/33] change `QualifiedName` to the new standard --- rust/src/binaryview.rs | 85 ++++++++++++++++-------------------------- rust/src/types.rs | 41 ++++++++++++++++---- 2 files changed, 67 insertions(+), 59 deletions(-) diff --git a/rust/src/binaryview.rs b/rust/src/binaryview.rs index 5f5d3c7d1..04d5f50da 100644 --- a/rust/src/binaryview.rs +++ b/rust/src/binaryview.rs @@ -49,6 +49,7 @@ use crate::segment::{Segment, SegmentBuilder}; use crate::settings::Settings; use crate::symbol::{Symbol, SymbolType}; use crate::tags::{Tag, TagType}; +use crate::types::QualifiedNameTypeAndId; use crate::types::{ Conf, DataVariable, NamedTypeReference, QualifiedName, QualifiedNameAndType, Type, }; @@ -616,32 +617,24 @@ pub trait BinaryViewExt: BinaryViewBase { names_sources_and_types: Vec<(S, S, &Type)>, progress: Option Result<()>>>, ) -> HashMap { - let mut names = vec![]; - let mut ids = vec![]; - let mut types = vec![]; - let mut api_types = - Vec::::with_capacity(names_sources_and_types.len()); - for (name, source, type_obj) in names_sources_and_types.into_iter() { - names.push(QualifiedName::from(name)); - ids.push(source.into_bytes_with_nul()); - types.push(type_obj); - } - - for ((name, source), type_obj) in names.iter().zip(ids.iter()).zip(types.iter()) { - api_types.push(BNQualifiedNameTypeAndId { - name: name.0, - id: source.as_ref().as_ptr() as *mut _, - type_: type_obj.as_raw(), - }); - } - + let mut api_types: Vec = names_sources_and_types + .into_iter() + .map(|(name, source, type_obj)| { + QualifiedNameTypeAndId::new(name, source, type_obj.to_owned()) + }) + .collect(); + + // SAFETY: QualifiedNameTypeAndId and BNQualifiedNameTypeAndId are + // transparent + let api_types_raw: &mut [BNQualifiedNameTypeAndId] = + unsafe { core::mem::transmute(api_types.as_mut_slice()) }; let mut progress_raw = ProgressContext(progress); let mut result_ids: *mut *mut c_char = ptr::null_mut(); let mut result_names: *mut BNQualifiedName = ptr::null_mut(); let result_count = unsafe { BNDefineAnalysisTypes( self.as_ref().handle, - api_types.as_mut_ptr(), + api_types_raw.as_mut_ptr(), api_types.len(), Some(cb_progress), &mut progress_raw as *mut _ as *mut c_void, @@ -667,26 +660,19 @@ pub trait BinaryViewExt: BinaryViewBase { names_and_types: Vec<(S, &Type)>, progress: Option Result<()>>>, ) { - let mut names = vec![]; - let mut types = vec![]; - let mut api_types = Vec::::with_capacity(names_and_types.len()); - for (name, type_obj) in names_and_types.into_iter() { - names.push(QualifiedName::from(name)); - types.push(type_obj); - } - - for (name, type_obj) in names.iter().zip(types.iter()) { - api_types.push(BNQualifiedNameAndType { - name: name.0, - type_: type_obj.as_raw(), - }); - } + let mut api_types: Vec = names_and_types + .into_iter() + .map(|(name, type_obj)| QualifiedNameAndType::new(name, type_obj.to_owned())) + .collect(); + // SAFETY: QualifiedNameType and BNQualifiedNameType are transparent + let api_types_raw: &mut [BNQualifiedNameAndType] = + unsafe { core::mem::transmute(api_types.as_mut_slice()) }; let mut progress_raw = ProgressContext(progress); unsafe { BNDefineUserAnalysisTypes( self.as_ref().handle, - api_types.as_mut_ptr(), + api_types_raw.as_mut_ptr(), api_types.len(), Some(cb_progress), &mut progress_raw as *mut _ as *mut c_void, @@ -703,7 +689,7 @@ pub trait BinaryViewExt: BinaryViewBase { fn undefine_user_type(&self, name: S) { let mut qualified_name = QualifiedName::from(name); - unsafe { BNUndefineUserAnalysisType(self.as_ref().handle, &mut qualified_name.0) } + unsafe { BNUndefineUserAnalysisType(self.as_ref().handle, qualified_name.as_raw_mut()) } } fn types(&self) -> Array { @@ -725,7 +711,8 @@ pub trait BinaryViewExt: BinaryViewBase { fn get_type_by_name(&self, name: S) -> Option { unsafe { let mut qualified_name = QualifiedName::from(name); - let type_handle = BNGetAnalysisTypeByName(self.as_ref().handle, &mut qualified_name.0); + let type_handle = + BNGetAnalysisTypeByName(self.as_ref().handle, qualified_name.as_raw_mut()); if type_handle.is_null() { return None; } @@ -760,7 +747,7 @@ pub trait BinaryViewExt: BinaryViewBase { let id_str = id.into_bytes_with_nul(); let name_handle = BNGetAnalysisTypeNameById(self.as_ref().handle, id_str.as_ref().as_ptr() as *mut _); - let name = QualifiedName(name_handle); + let name = QualifiedName::from_raw(name_handle); if name.strings().is_empty() { return None; } @@ -771,7 +758,7 @@ pub trait BinaryViewExt: BinaryViewBase { fn get_type_id(&self, name: S) -> Option { unsafe { let mut qualified_name = QualifiedName::from(name); - let id_cstr = BNGetAnalysisTypeId(self.as_ref().handle, &mut qualified_name.0); + let id_cstr = BNGetAnalysisTypeId(self.as_ref().handle, qualified_name.as_raw_mut()); let id = BnString::from_raw(ptr::NonNull::new(id_cstr).unwrap()); if id.is_empty() { return None; @@ -783,7 +770,7 @@ pub trait BinaryViewExt: BinaryViewBase { fn is_type_auto_defined(&self, name: S) -> bool { unsafe { let mut qualified_name = QualifiedName::from(name); - BNIsAnalysisTypeAutoDefined(self.as_ref().handle, &mut qualified_name.0) + BNIsAnalysisTypeAutoDefined(self.as_ref().handle, qualified_name.as_raw_mut()) } } @@ -1319,12 +1306,9 @@ pub trait BinaryViewExt: BinaryViewBase { fn get_code_refs_for_type(&self, name: B) -> Array { unsafe { let mut count = 0; - let q_name = &mut QualifiedName::from(name).0; - let handle = BNGetCodeReferencesForType( - self.as_ref().handle, - q_name as *mut BNQualifiedName, - &mut count, - ); + let mut q_name = QualifiedName::from(name); + let handle = + BNGetCodeReferencesForType(self.as_ref().handle, q_name.as_raw_mut(), &mut count); Array::new(handle, count, ()) } } @@ -1337,12 +1321,9 @@ pub trait BinaryViewExt: BinaryViewBase { fn get_data_refs_for_type(&self, name: B) -> Array { unsafe { let mut count = 0; - let q_name = &mut QualifiedName::from(name).0; - let handle = BNGetDataReferencesForType( - self.as_ref().handle, - q_name as *mut BNQualifiedName, - &mut count, - ); + let mut q_name = QualifiedName::from(name); + let handle = + BNGetDataReferencesForType(self.as_ref().handle, q_name.as_raw_mut(), &mut count); Array::new(handle, count, ()) } } diff --git a/rust/src/types.rs b/rust/src/types.rs index 6a2827e52..4ea32b3a2 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -2513,6 +2513,14 @@ pub struct QualifiedNameAndType { } impl QualifiedNameAndType { + pub fn new(name: N, type_: Type) -> Self { + let name: QualifiedName = name.into(); + Self { + name: ManuallyDrop::new(name), + type_: ManuallyDrop::new(type_), + } + } + pub(crate) unsafe fn ref_from_raw(handle: &BNQualifiedNameAndType) -> &QualifiedNameAndType { mem::transmute(handle) } @@ -2554,27 +2562,46 @@ unsafe impl CoreArrayProviderInner for QualifiedNameAndType { ////////////////////////// // QualifiedNameTypeAndId -#[repr(transparent)] -pub struct QualifiedNameTypeAndId(pub(crate) BNQualifiedNameTypeAndId); +#[repr(C)] +#[derive(Debug, Clone)] +pub struct QualifiedNameTypeAndId { + // Drop is done by BNFreeQualifiedNameTypeAndId + name: ManuallyDrop, + id: ManuallyDrop, + type_: ManuallyDrop, +} impl QualifiedNameTypeAndId { + pub fn new(name: N, id: I, type_: Type) -> Self { + let name: QualifiedName = name.into(); + Self { + name: ManuallyDrop::new(name), + id: ManuallyDrop::new(BnString::new(id)), + type_: ManuallyDrop::new(type_), + } + } + + pub(crate) fn as_raw_mut(&mut self) -> &mut BNQualifiedNameTypeAndId { + unsafe { mem::transmute(self) } + } + pub fn name(&self) -> &QualifiedName { - unsafe { mem::transmute(&self.0.name) } + &self.name } pub fn id(&self) -> &str { - unsafe { CStr::from_ptr(self.0.id).to_str().unwrap() } + self.id.as_str() } - pub fn type_object(&self) -> Guard { - unsafe { Guard::new(Type::from_raw(NonNull::new(self.0.type_).unwrap()), self) } + pub fn type_object(&self) -> &Type { + &self.type_ } } impl Drop for QualifiedNameTypeAndId { fn drop(&mut self) { unsafe { - BNFreeQualifiedNameTypeAndId(&mut self.0); + BNFreeQualifiedNameTypeAndId(self.as_raw_mut()); } } } From 456a05ddd879b4097a600f816ab1b1e333e8d7f8 Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Wed, 29 May 2024 18:05:57 -0300 Subject: [PATCH 17/33] change `NameAndType` to the new standard --- rust/src/architecture.rs | 44 ++++++-------------------- rust/src/debuginfo.rs | 28 +++++------------ rust/src/rc.rs | 12 +++++++ rust/src/types.rs | 67 ++++++++++++---------------------------- 4 files changed, 48 insertions(+), 103 deletions(-) diff --git a/rust/src/architecture.rs b/rust/src/architecture.rs index e8e5e204b..d6f11f381 100644 --- a/rust/src/architecture.rs +++ b/rust/src/architecture.rs @@ -24,9 +24,7 @@ use std::{ ffi::{c_char, c_int, CStr, CString}, hash::Hash, mem::{zeroed, MaybeUninit}, - ops, - ptr, - slice, + ops, ptr, slice, }; use crate::{ @@ -315,7 +313,7 @@ pub trait Intrinsic: Sized + Clone + Copy { fn id(&self) -> u32; /// Reeturns the list of the input names and types for this intrinsic. - fn inputs(&self) -> Vec>; + fn inputs(&self) -> Array; /// Returns the list of the output types for this intrinsic. fn outputs(&self) -> Vec>; @@ -652,7 +650,7 @@ impl Intrinsic for UnusedIntrinsic { fn id(&self) -> u32 { unreachable!() } - fn inputs(&self) -> Vec> { + fn inputs(&self) -> Array { unreachable!() } fn outputs(&self) -> Vec> { @@ -1009,20 +1007,12 @@ impl Intrinsic for crate::architecture::CoreIntrinsic { self.1 } - fn inputs(&self) -> Vec> { + fn inputs(&self) -> Array { let mut count: usize = 0; unsafe { let inputs = BNGetArchitectureIntrinsicInputs(self.0, self.1, &mut count as *mut _); - - let ret = slice::from_raw_parts_mut(inputs, count) - .iter() - .map(|x| NameAndType::from_raw(x).to_owned()) - .collect(); - - BNFreeNameAndTypeList(inputs, count); - - ret + Array::new(inputs, count, ()) } } @@ -2435,21 +2425,10 @@ where return ptr::null_mut(); }; - let inputs = intrinsic.inputs(); - let mut res: Box<[_]> = inputs - .into_iter() - .map(|input| unsafe { Ref::into_raw(input) }.0) - .collect(); - unsafe { - *count = res.len(); - if res.is_empty() { - ptr::null_mut() - } else { - let raw = res.as_mut_ptr(); - mem::forget(res); - raw - } + let (inputs, inputs_len, ()) = intrinsic.inputs().into_raw(); + *count = inputs_len; + inputs } } @@ -2460,12 +2439,7 @@ where let _custom_arch = unsafe { &*(ctxt as *mut A) }; if !nt.is_null() { - unsafe { - let name_and_types = Box::from_raw(ptr::slice_from_raw_parts_mut(nt, count)); - for nt in name_and_types.iter() { - Ref::new(NameAndType::from_raw(nt)); - } - } + let _array: Array = unsafe { Array::new(nt, count, ()) }; } } diff --git a/rust/src/debuginfo.rs b/rust/src/debuginfo.rs index 44e3ca5d5..8a7933af0 100644 --- a/rust/src/debuginfo.rs +++ b/rust/src/debuginfo.rs @@ -389,7 +389,7 @@ impl DebugInfo { } /// Returns a generator of all types provided by a named DebugInfoParser - pub fn types_by_name(&self, parser_name: S) -> Vec> { + pub fn types_by_name(&self, parser_name: S) -> Array { let parser_name = parser_name.into_bytes_with_nul(); let mut count: usize = 0; @@ -400,30 +400,18 @@ impl DebugInfo { &mut count, ) }; - let result: Vec> = unsafe { - slice::from_raw_parts_mut(debug_types_ptr, count) - .iter() - .map(|x| NameAndType::from_raw(x).to_owned()) - .collect() - }; - - unsafe { BNFreeDebugTypes(debug_types_ptr, count) }; - result + // BNFreeDebugTypes is identical to BNFreeNameAndTypeList, so we can use + // Array here with no consequences + unsafe{Array::new(debug_types_ptr, count, ())} } /// A generator of all types provided by DebugInfoParsers - pub fn types(&self) -> Vec> { + pub fn types(&self) -> Array { let mut count: usize = 0; let debug_types_ptr = unsafe { BNGetDebugTypes(self.handle, ptr::null_mut(), &mut count) }; - let result: Vec> = unsafe { - slice::from_raw_parts_mut(debug_types_ptr, count) - .iter() - .map(|x| NameAndType::from_raw(x).to_owned()) - .collect() - }; - - unsafe { BNFreeDebugTypes(debug_types_ptr, count) }; - result + // BNFreeDebugTypes is identical to BNFreeNameAndTypeList, so we can use + // Array here with no consequences + unsafe{Array::new(debug_types_ptr, count, ())} } /// Returns a generator of all functions provided by a named DebugInfoParser diff --git a/rust/src/rc.rs b/rust/src/rc.rs index dc1a502bb..f2c8da12a 100644 --- a/rust/src/rc.rs +++ b/rust/src/rc.rs @@ -233,6 +233,18 @@ impl Array

{ } } + pub(crate) unsafe fn into_raw(self) -> (*mut P::Raw, usize, P::Context) { + let contents = self.contents; + let count = self.count; + + // extract the context, because we can't move it directly, we need + // to be carefull to take the value, not droping self + let slf = mem::ManuallyDrop::new(self); + let context = mem::transmute_copy(&slf.context); + + (contents, count, context) + } + #[inline] pub fn len(&self) -> usize { self.count diff --git a/rust/src/types.rs b/rust/src/types.rs index 4ea32b3a2..df5fb13e7 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -711,11 +711,6 @@ impl Type { Self { handle } } - pub(crate) unsafe fn ref_from_raw(handle: &*mut BNType) -> &Self { - assert!(!handle.is_null()); - mem::transmute(handle) - } - pub(crate) fn as_raw(&self) -> &mut BNType { unsafe { &mut (*self.handle.as_ptr()) } } @@ -2623,68 +2618,44 @@ unsafe impl CoreArrayProviderInner for QualifiedNameTypeAndId { ////////////////////////// // NameAndType -pub struct NameAndType(pub(crate) BNNameAndType); +#[repr(C)] +#[derive(Debug, Clone)] +pub struct NameAndType { + name: BnString, + type_: Type, + type_confidence: u8, +} impl NameAndType { - pub(crate) unsafe fn from_raw(raw: &BNNameAndType) -> Self { - Self(*raw) + pub(crate) unsafe fn ref_from_raw(raw: &BNNameAndType) -> &Self { + mem::transmute(raw) } -} -impl NameAndType { - pub fn new(name: S, t: Type, confidence: u8) -> Ref { - unsafe { - Ref::new(Self(BNNameAndType { - name: BNAllocString(name.into_bytes_with_nul().as_ref().as_ptr() as *mut _), - type_: t.into_raw(), - typeConfidence: confidence, - })) + pub fn new(name: S, t: Type, confidence: u8) -> Self { + Self { + name: BnString::new(name), + type_: t, + type_confidence: confidence, } } pub fn name(&self) -> &str { - let c_str = unsafe { CStr::from_ptr(self.0.name) }; - c_str.to_str().unwrap() + self.name.as_str() } pub fn t(&self) -> &Type { - unsafe { Type::ref_from_raw(&self.0.type_) } + &self.type_ } pub fn type_with_confidence(&self) -> Conf<&Type> { - Conf::new(self.t(), self.0.typeConfidence) - } -} - -impl ToOwned for NameAndType { - type Owned = Ref; - - fn to_owned(&self) -> Self::Owned { - unsafe { RefCountable::inc_ref(self) } - } -} - -unsafe impl RefCountable for NameAndType { - unsafe fn inc_ref(handle: &Self) -> Ref { - Self::new( - CStr::from_ptr(handle.0.name), - handle.t().clone(), - handle.0.typeConfidence, - ) - } - - unsafe fn dec_ref(handle: &Self) { - unsafe { - BNFreeString(handle.0.name); - let _ = Type::from_raw(NonNull::new(handle.0.type_).unwrap()); - } + Conf::new(self.t(), self.type_confidence) } } impl CoreArrayProvider for NameAndType { type Raw = BNNameAndType; type Context = (); - type Wrapped<'a> = Guard<'a, NameAndType>; + type Wrapped<'a> = &'a NameAndType; } unsafe impl CoreArrayProviderInner for NameAndType { @@ -2692,7 +2663,7 @@ unsafe impl CoreArrayProviderInner for NameAndType { BNFreeNameAndTypeList(raw, count); } unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> { - unsafe { Guard::new(NameAndType::from_raw(raw), raw) } + NameAndType::ref_from_raw(raw) } } From 0fcc1fa260eca1f6bce0099eac482ea12acde695 Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Wed, 29 May 2024 18:13:59 -0300 Subject: [PATCH 18/33] change `DataVariable` to the new standard --- rust/src/types.rs | 69 +++++++++++++++++++---------------------------- 1 file changed, 27 insertions(+), 42 deletions(-) diff --git a/rust/src/types.rs b/rust/src/types.rs index df5fb13e7..788638159 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -715,10 +715,6 @@ impl Type { unsafe { &mut (*self.handle.as_ptr()) } } - pub(crate) fn into_raw(self) -> *mut BNType { - ManuallyDrop::new(self).handle.as_ptr() - } - pub fn to_builder(&self) -> TypeBuilder { TypeBuilder::new(self) } @@ -2670,61 +2666,48 @@ unsafe impl CoreArrayProviderInner for NameAndType { ////////////////// // DataVariable -#[repr(transparent)] -pub struct DataVariable(pub(crate) BNDataVariable); - -// impl DataVariable { -// pub(crate) fn from_raw(var: &BNDataVariable) -> Self { -// let var = DataVariable(*var); -// Self(BNDataVariable { -// type_: unsafe { Ref::into_raw(var.t().to_owned()).handle }, -// ..var.0 -// }) -// } -// } +#[repr(C)] +pub struct DataVariable { + pub address: u64, + // droped by BNFreeDataVariable + type_: ManuallyDrop, + auto_discovered: bool, + type_confidence: u8, +} impl DataVariable { + pub(crate) unsafe fn ref_from_raw(value: &BNDataVariable) -> &Self { + mem::transmute(value) + } + + pub(crate) fn as_raw_mut(&mut self) -> &mut BNDataVariable { + unsafe { mem::transmute(self) } + } + pub fn address(&self) -> u64 { - self.0.address + self.address } pub fn auto_discovered(&self) -> bool { - self.0.autoDiscovered + self.auto_discovered } pub fn t(&self) -> &Type { - unsafe { mem::transmute(&self.0.type_) } + &self.type_ } pub fn type_with_confidence(&self) -> Conf<&Type> { - Conf::new(self.t(), self.0.typeConfidence) + Conf::new(self.t(), self.type_confidence) } pub fn symbol(&self, bv: &BinaryView) -> Option> { - bv.symbol_by_address(self.0.address).ok() + bv.symbol_by_address(self.address).ok() } } -impl ToOwned for DataVariable { - type Owned = Ref; - - fn to_owned(&self) -> Self::Owned { - unsafe { RefCountable::inc_ref(self) } - } -} - -unsafe impl RefCountable for DataVariable { - unsafe fn inc_ref(handle: &Self) -> Ref { - unsafe { - Ref::new(Self(BNDataVariable { - type_: handle.t().clone().into_raw(), - ..handle.0 - })) - } - } - - unsafe fn dec_ref(handle: &Self) { - unsafe { BNFreeType(handle.0.type_) } +impl Drop for DataVariable { + fn drop(&mut self) { + unsafe { BNFreeDataVariable(self.as_raw_mut()) } } } @@ -2733,12 +2716,14 @@ impl CoreArrayProvider for DataVariable { type Context = (); type Wrapped<'a> = &'a DataVariable; } + unsafe impl CoreArrayProviderInner for DataVariable { unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) { BNFreeDataVariables(raw, count); } + unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> { - mem::transmute(raw) + DataVariable::ref_from_raw(raw) } } From 3788dc5c4a6b2050cbeb03baa66fac947e797c64 Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Wed, 29 May 2024 18:45:19 -0300 Subject: [PATCH 19/33] change `DataVariableAndName` to the new standard --- rust/src/debuginfo.rs | 149 ++++++++---------------------------------- rust/src/types.rs | 83 ++++++++++++++++------- 2 files changed, 89 insertions(+), 143 deletions(-) diff --git a/rust/src/debuginfo.rs b/rust/src/debuginfo.rs index 8a7933af0..3c51dbd0c 100644 --- a/rust/src/debuginfo.rs +++ b/rust/src/debuginfo.rs @@ -402,7 +402,7 @@ impl DebugInfo { }; // BNFreeDebugTypes is identical to BNFreeNameAndTypeList, so we can use // Array here with no consequences - unsafe{Array::new(debug_types_ptr, count, ())} + unsafe { Array::new(debug_types_ptr, count, ()) } } /// A generator of all types provided by DebugInfoParsers @@ -411,7 +411,7 @@ impl DebugInfo { let debug_types_ptr = unsafe { BNGetDebugTypes(self.handle, ptr::null_mut(), &mut count) }; // BNFreeDebugTypes is identical to BNFreeNameAndTypeList, so we can use // Array here with no consequences - unsafe{Array::new(debug_types_ptr, count, ())} + unsafe { Array::new(debug_types_ptr, count, ()) } } /// Returns a generator of all functions provided by a named DebugInfoParser @@ -459,7 +459,7 @@ impl DebugInfo { pub fn data_variables_by_name( &self, parser_name: S, - ) -> Vec> { + ) -> Array { let parser_name = parser_name.into_bytes_with_nul(); let mut count: usize = 0; @@ -471,36 +471,24 @@ impl DebugInfo { ) }; - let result: Vec> = unsafe { - slice::from_raw_parts_mut(data_variables_ptr, count) - .iter() - .map(DataVariableAndName::::from_raw) - .collect() - }; - - unsafe { BNFreeDataVariablesAndName(data_variables_ptr, count) }; - result + unsafe { Array::new(data_variables_ptr, count, ()) } } /// A generator of all data variables provided by DebugInfoParsers - pub fn data_variables(&self) -> Vec> { + pub fn data_variables(&self) -> Array { let mut count: usize = 0; let data_variables_ptr = unsafe { BNGetDebugDataVariables(self.handle, ptr::null_mut(), &mut count) }; - let result: Vec> = unsafe { - slice::from_raw_parts_mut(data_variables_ptr, count) - .iter() - .map(DataVariableAndName::::from_raw) - .collect() - }; - - unsafe { BNFreeDataVariablesAndName(data_variables_ptr, count) }; - result + unsafe { Array::new(data_variables_ptr, count, ()) } } /// May return nullptr - pub fn type_by_name(&self, parser_name: S, name: S) -> Option { + pub fn type_by_name( + &self, + parser_name: S1, + name: S1, + ) -> Option { let parser_name = parser_name.into_bytes_with_nul(); let name = name.into_bytes_with_nul(); @@ -518,10 +506,10 @@ impl DebugInfo { } } - pub fn get_data_variable_by_name( + pub fn get_data_variable_by_name( &self, - parser_name: S, - name: S, + parser_name: S1, + name: S2, ) -> Option<(u64, Type)> { let parser_name = parser_name.into_bytes_with_nul(); let name = name.into_bytes_with_nul(); @@ -533,21 +521,11 @@ impl DebugInfo { name.as_ref().as_ptr() as *mut _, ) }; - - if !result.is_null() { - let BNDataVariableAndName { - address, - type_, - name, - autoDiscovered: _, - typeConfidence: _, - } = unsafe { *result }; - unsafe { BNFreeString(name) }; - let var_type = unsafe { Type::from_raw(ptr::NonNull::new(type_).unwrap()) }; - Some((address, var_type)) - } else { - None + if result.is_null() { + return None; } + let result = unsafe { DataVariableAndName::ref_from_raw(&*result) }; + Some((result.address, result.t.clone())) } pub fn get_data_variable_by_address( @@ -564,29 +542,15 @@ impl DebugInfo { ) }; - if !name_and_var.is_null() { - let BNDataVariableAndName { - address: _, - type_, - name, - autoDiscovered: _, - typeConfidence: _, - } = unsafe { *name_and_var }; - let result = unsafe { - ( - raw_to_string(name).unwrap(), - Type::from_raw(ptr::NonNull::new(type_).unwrap()), - ) - }; - unsafe { BNFreeString(name) }; - Some(result) - } else { - None + if name_and_var.is_null() { + return None; } + let result = unsafe { DataVariableAndName::ref_from_raw(&*name_and_var) }; + Some((result.name().to_owned(), result.t.clone())) } // The tuple is (DebugInfoParserName, type) - pub fn get_types_by_name(&self, name: S) -> Vec<(String, Type)> { + pub fn get_types_by_name(&self, name: S) -> Array { let name = name.into_bytes_with_nul(); let mut count: usize = 0; @@ -594,35 +558,14 @@ impl DebugInfo { BNGetDebugTypesByName(self.handle, name.as_ref().as_ptr() as *mut _, &mut count) }; - let names_and_types: &[*mut BNNameAndType] = - unsafe { slice::from_raw_parts(raw_names_and_types as *mut _, count) }; - - let result = names_and_types - .iter() - .take(count) - .map(|&name_and_type| unsafe { - assert!(!name_and_type.is_null()); - let BNNameAndType { - name, - type_, - typeConfidence: _, - } = *name_and_type; - ( - raw_to_string(name).unwrap(), - Type::from_raw(ptr::NonNull::new(BNNewTypeReference(type_)).unwrap()), - ) - }) - .collect(); - - unsafe { BNFreeNameAndTypeList(raw_names_and_types, count) }; - result + unsafe { Array::new(raw_names_and_types, count, ()) } } // The tuple is (DebugInfoParserName, address, type) pub fn get_data_variables_by_name( &self, name: S, - ) -> Vec<(String, u64, Type)> { + ) -> Array { let name = name.into_bytes_with_nul(); let mut count: usize = 0; @@ -630,31 +573,7 @@ impl DebugInfo { BNGetDebugDataVariablesByName(self.handle, name.as_ref().as_ptr() as *mut _, &mut count) }; - let variables_and_names: &[*mut BNDataVariableAndName] = - unsafe { slice::from_raw_parts(raw_variables_and_names as *mut _, count) }; - - let result = variables_and_names - .iter() - .take(count) - .map(|&variable_and_name| unsafe { - assert!(!variable_and_name.is_null()); - let BNDataVariableAndName { - address, - type_, - name, - autoDiscovered: _, - typeConfidence: _, - } = *variable_and_name; - ( - raw_to_string(name).unwrap(), - address, - Type::from_raw(ptr::NonNull::new(BNNewTypeReference(type_)).unwrap()), - ) - }) - .collect(); - - unsafe { BNFreeDataVariablesAndName(raw_variables_and_names, count) }; - result + unsafe { Array::new(raw_variables_and_names, count, ()) } } /// The tuple is (DebugInfoParserName, TypeName, type) @@ -874,20 +793,8 @@ impl DebugInfo { } } - pub fn add_data_variable_info(&self, var: DataVariableAndName) -> bool { - let name = var.name.into_bytes_with_nul(); - unsafe { - BNAddDebugDataVariableInfo( - self.handle, - &BNDataVariableAndName { - address: var.address, - type_: var.t.contents.as_raw(), - name: name.as_ref().as_ptr() as *mut _, - autoDiscovered: var.auto_discovered, - typeConfidence: var.t.confidence, - }, - ) - } + pub fn add_data_variable_info(&self, var: DataVariableAndName) -> bool { + unsafe { BNAddDebugDataVariableInfo(self.handle, var.as_raw()) } } } diff --git a/rust/src/types.rs b/rust/src/types.rs index 788638159..0c9dc6001 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -26,7 +26,7 @@ use crate::{ function::Function, mlil::MediumLevelILFunction, rc::*, - string::{raw_to_string, BnStrCompatible, BnString}, + string::{BnStrCompatible, BnString}, symbol::Symbol, }; @@ -2730,39 +2730,73 @@ unsafe impl CoreArrayProviderInner for DataVariable { ///////////////////////// // DataVariableAndName -pub struct DataVariableAndName { +#[repr(C)] +pub struct DataVariableAndName { pub address: u64, - pub t: Conf, + pub t: Type, + name: BnString, pub auto_discovered: bool, - pub name: S, + type_confidence: u8, } -impl DataVariableAndName { - pub(crate) fn from_raw(var: &BNDataVariableAndName) -> Self { - Self { - address: var.address, - t: Conf::new( - unsafe { Type::from_raw(NonNull::new(var.type_).unwrap()) }, - var.typeConfidence, - ), - auto_discovered: var.autoDiscovered, - name: raw_to_string(var.name).unwrap(), - } +impl DataVariableAndName { + pub(crate) unsafe fn ref_from_raw(var: &BNDataVariableAndName) -> &Self { + unsafe { mem::transmute(var) } + } + + pub(crate) fn as_raw(&self) -> &BNDataVariableAndName { + unsafe { mem::transmute(self) } + } + + pub(crate) fn as_raw_mut(&mut self) -> &mut BNDataVariableAndName { + unsafe { mem::transmute(self) } } -} -impl DataVariableAndName { - pub fn new(address: u64, t: Conf, auto_discovered: bool, name: S) -> Self { + pub fn new( + address: u64, + t: Conf, + auto_discovered: bool, + name: S, + ) -> Self { Self { address, - t, + t: t.contents, + name: BnString::new(name), auto_discovered, - name, + type_confidence: t.confidence, } } - pub fn type_with_confidence(&self) -> Conf { - Conf::new(self.t.contents.clone(), self.t.confidence) + pub fn name(&self) -> &str { + self.name.as_str() + } + + pub fn type_with_confidence(&self) -> Conf<&Type> { + Conf::new(&self.t, self.type_confidence) + } +} + +impl Drop for DataVariableAndName { + fn drop(&mut self) { + unsafe{ + BNFreeDataVariableAndName(self.as_raw_mut()) + } + } +} + +impl CoreArrayProvider for DataVariableAndName { + type Raw = BNDataVariableAndName; + type Context = (); + type Wrapped<'a> = &'a Self; +} + +unsafe impl CoreArrayProviderInner for DataVariableAndName { + unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) { + unsafe { BNFreeDataVariablesAndName(raw, count) }; + } + + unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> { + Self::ref_from_raw(raw) } } @@ -3783,4 +3817,9 @@ mod test { // TODO ::parse_types_from_source forgot to call // BNFreeTypeParserResult, leaking the result + + // TODO BNGetDebugDataVariableByName returns a *mut BNDataVariableAndName + // pointer, can we deref it? Or it need to be freed by proper drop. + // Verify if DebugInfo::get_data_variable_by_name should call + // BNFreeDataVariableAndName } From 747b7509f7355a55704c826a0ca2261a802f4c5d Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Wed, 29 May 2024 18:58:41 -0300 Subject: [PATCH 20/33] create `DataVariableAndNameAndDebugParser` to the new standard --- rust/src/debuginfo.rs | 63 +++++++++++++--------------------- rust/src/types.rs | 80 +++++++++++++++++++++++++++++++------------ 2 files changed, 82 insertions(+), 61 deletions(-) diff --git a/rust/src/debuginfo.rs b/rust/src/debuginfo.rs index 3c51dbd0c..f539fd904 100644 --- a/rust/src/debuginfo.rs +++ b/rust/src/debuginfo.rs @@ -75,7 +75,7 @@ use crate::{ platform::Platform, rc::*, string::{raw_to_string, BnStrCompatible, BnString}, - types::{DataVariableAndName, NameAndType, Type}, + types::{DataVariableAndName, DataVariableAndNameAndDebugParser, NameAndType, Type}, }; use std::{ @@ -514,18 +514,23 @@ impl DebugInfo { let parser_name = parser_name.into_bytes_with_nul(); let name = name.into_bytes_with_nul(); - let result = unsafe { + let name_and_var_raw = unsafe { BNGetDebugDataVariableByName( self.handle, parser_name.as_ref().as_ptr() as *mut _, name.as_ref().as_ptr() as *mut _, ) }; - if result.is_null() { + if name_and_var_raw.is_null() { return None; } - let result = unsafe { DataVariableAndName::ref_from_raw(&*result) }; - Some((result.address, result.t.clone())) + let name_and_var = unsafe { DataVariableAndName::ref_from_raw(&*name_and_var_raw) }; + let result = ( + name_and_var.address, + name_and_var.type_with_confidence().contents.clone(), + ); + unsafe { BNFreeDataVariableAndName(name_and_var_raw) }; + Some(result) } pub fn get_data_variable_by_address( @@ -534,7 +539,7 @@ impl DebugInfo { address: u64, ) -> Option<(String, Type)> { let parser_name = parser_name.into_bytes_with_nul(); - let name_and_var = unsafe { + let name_and_var_raw = unsafe { BNGetDebugDataVariableByAddress( self.handle, parser_name.as_ref().as_ptr() as *mut _, @@ -542,14 +547,18 @@ impl DebugInfo { ) }; - if name_and_var.is_null() { + if name_and_var_raw.is_null() { return None; } - let result = unsafe { DataVariableAndName::ref_from_raw(&*name_and_var) }; - Some((result.name().to_owned(), result.t.clone())) + let name_and_var = unsafe { DataVariableAndName::ref_from_raw(&*name_and_var_raw) }; + let result = ( + name_and_var.name().to_owned(), + name_and_var.type_with_confidence().contents.clone(), + ); + unsafe { BNFreeDataVariableAndName(name_and_var_raw) }; + Some(result) } - // The tuple is (DebugInfoParserName, type) pub fn get_types_by_name(&self, name: S) -> Array { let name = name.into_bytes_with_nul(); @@ -561,7 +570,6 @@ impl DebugInfo { unsafe { Array::new(raw_names_and_types, count, ()) } } - // The tuple is (DebugInfoParserName, address, type) pub fn get_data_variables_by_name( &self, name: S, @@ -576,38 +584,15 @@ impl DebugInfo { unsafe { Array::new(raw_variables_and_names, count, ()) } } - /// The tuple is (DebugInfoParserName, TypeName, type) - pub fn get_data_variables_by_address(&self, address: u64) -> Vec<(String, String, Type)> { + pub fn get_data_variables_by_address( + &self, + address: u64, + ) -> Array { let mut count: usize = 0; let raw_variables_and_names = unsafe { BNGetDebugDataVariablesByAddress(self.handle, address, &mut count) }; - let variables_and_names: &[*mut BNDataVariableAndNameAndDebugParser] = - unsafe { slice::from_raw_parts(raw_variables_and_names as *mut _, count) }; - - let result = variables_and_names - .iter() - .take(count) - .map(|&variable_and_name| unsafe { - assert!(!variable_and_name.is_null()); - let BNDataVariableAndNameAndDebugParser { - address: _, - type_, - name, - parser, - autoDiscovered: _, - typeConfidence: _, - } = *variable_and_name; - ( - raw_to_string(parser).unwrap(), - raw_to_string(name).unwrap(), - Type::from_raw(ptr::NonNull::new(BNNewTypeReference(type_)).unwrap()), - ) - }) - .collect(); - - unsafe { BNFreeDataVariableAndNameAndDebugParserList(raw_variables_and_names, count) }; - result + unsafe { Array::new(raw_variables_and_names, count, ()) } } pub fn remove_parser_info(&self, parser_name: S) -> bool { diff --git a/rust/src/types.rs b/rust/src/types.rs index 0c9dc6001..fbf0adbc2 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -2733,8 +2733,8 @@ unsafe impl CoreArrayProviderInner for DataVariable { #[repr(C)] pub struct DataVariableAndName { pub address: u64, - pub t: Type, - name: BnString, + t: ManuallyDrop, + name: ManuallyDrop, pub auto_discovered: bool, type_confidence: u8, } @@ -2752,21 +2752,6 @@ impl DataVariableAndName { unsafe { mem::transmute(self) } } - pub fn new( - address: u64, - t: Conf, - auto_discovered: bool, - name: S, - ) -> Self { - Self { - address, - t: t.contents, - name: BnString::new(name), - auto_discovered, - type_confidence: t.confidence, - } - } - pub fn name(&self) -> &str { self.name.as_str() } @@ -2778,9 +2763,7 @@ impl DataVariableAndName { impl Drop for DataVariableAndName { fn drop(&mut self) { - unsafe{ - BNFreeDataVariableAndName(self.as_raw_mut()) - } + unsafe { BNFreeDataVariableAndName(self.as_raw_mut()) } } } @@ -2800,6 +2783,54 @@ unsafe impl CoreArrayProviderInner for DataVariableAndName { } } +///////////////////////// +// DataVariableAndNameAndDebugParser + +#[repr(C)] +#[derive(Debug, Clone)] +pub struct DataVariableAndNameAndDebugParser { + pub address: u64, + pub t: Type, + name: BnString, + parser: BnString, + pub auto_discovered: bool, + type_confidence: u8, +} + +impl DataVariableAndNameAndDebugParser { + pub(crate) unsafe fn ref_from_raw(var: &BNDataVariableAndNameAndDebugParser) -> &Self { + unsafe { mem::transmute(var) } + } + + pub fn name(&self) -> &str { + self.name.as_str() + } + + pub fn parser(&self) -> &str { + self.parser.as_str() + } + + pub fn type_with_confidence(&self) -> Conf<&Type> { + Conf::new(&self.t, self.type_confidence) + } +} + +impl CoreArrayProvider for DataVariableAndNameAndDebugParser { + type Raw = BNDataVariableAndNameAndDebugParser; + type Context = (); + type Wrapped<'a> = &'a Self; +} + +unsafe impl CoreArrayProviderInner for DataVariableAndNameAndDebugParser { + unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) { + unsafe { BNFreeDataVariableAndNameAndDebugParserList(raw, count) }; + } + + unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> { + Self::ref_from_raw(raw) + } +} + ///////////////////////// // RegisterValueType @@ -3820,6 +3851,11 @@ mod test { // TODO BNGetDebugDataVariableByName returns a *mut BNDataVariableAndName // pointer, can we deref it? Or it need to be freed by proper drop. - // Verify if DebugInfo::get_data_variable_by_name should call - // BNFreeDataVariableAndName + // Verify if + // * DebugInfo::get_data_variable_by_name + // * DebugInfo::get_data_variable_by_address + // should call BNFreeDataVariableAndName + // Also verify if + // * DebugInfo::add_data_variable_info + // should receive a reference or some kind of owned pointer } From 09acf14005b86e99b05ccdc3b52427dd376d691a Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Thu, 30 May 2024 08:59:33 -0300 Subject: [PATCH 21/33] change `InheritedStructureMember` to the new standard --- rust/src/types.rs | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/rust/src/types.rs b/rust/src/types.rs index fbf0adbc2..158bc887f 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -2162,6 +2162,7 @@ unsafe impl CoreArrayProviderInner for StructureMember { } } +#[repr(C)] #[derive(Debug, Clone)] pub struct InheritedStructureMember { pub base: NamedTypeReference, @@ -2185,14 +2186,35 @@ impl InheritedStructureMember { } } - // pub(crate) unsafe fn from_raw(handle: BNInheritedStructureMember) -> Self { - // Self { - // base: RefCountable::inc_ref(&NamedTypeReference::from_raw(handle.base)), - // base_offset: handle.baseOffset, - // member: StructureMember::from_raw(handle.member), - // member_index: handle.memberIndex, - // } - // } + pub(crate) unsafe fn ref_from_raw(handle: &BNInheritedStructureMember) -> &Self { + mem::transmute(handle) + } + + pub(crate) fn as_raw_mut(&mut self) -> &mut BNInheritedStructureMember { + unsafe { mem::transmute(self) } + } +} + +impl Drop for InheritedStructureMember { + fn drop(&mut self) { + unsafe { BNFreeInheritedStructureMember(self.as_raw_mut()) } + } +} + +impl CoreArrayProvider for InheritedStructureMember { + type Raw = BNInheritedStructureMember ; + type Context = (); + type Wrapped<'a> = &'a Self; +} + +unsafe impl CoreArrayProviderInner for InheritedStructureMember { + unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) { + BNFreeInheritedStructureMemberList(raw, count) + } + + unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> { + Self::ref_from_raw(raw) + } } #[repr(C)] @@ -3851,7 +3873,7 @@ mod test { // TODO BNGetDebugDataVariableByName returns a *mut BNDataVariableAndName // pointer, can we deref it? Or it need to be freed by proper drop. - // Verify if + // Verify if // * DebugInfo::get_data_variable_by_name // * DebugInfo::get_data_variable_by_address // should call BNFreeDataVariableAndName From 8a36bd395155509763c27e972d36e7a9d069d822 Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Thu, 30 May 2024 09:39:00 -0300 Subject: [PATCH 22/33] change `QualifiedName` to the new standard --- rust/src/types.rs | 129 ++++++++++++++++++++++++---------------------- 1 file changed, 66 insertions(+), 63 deletions(-) diff --git a/rust/src/types.rs b/rust/src/types.rs index 158bc887f..a131e1780 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -588,7 +588,7 @@ impl TypeBuilder { unsafe { let result = BNCreateNamedTypeReferenceBuilderFromTypeAndId( BnString::new("").as_ptr() as *mut _, - &mut name.0, + name.as_raw_mut(), t.as_raw(), ); Self::from_raw(NonNull::new(result).unwrap()) @@ -957,7 +957,7 @@ impl Type { unsafe { let result = BNCreateNamedTypeReferenceFromTypeAndId( BnString::new("").as_ptr() as *mut _, - &mut name.0, + name.as_raw_mut(), t.as_raw(), ); Self::from_raw(NonNull::new(result).unwrap()) @@ -1147,7 +1147,9 @@ impl Type { pub fn generate_auto_demangled_type_id(name: S) -> BnString { let mut name = QualifiedName::from(name); unsafe { - BnString::from_raw(NonNull::new(BNGenerateAutoDemangledTypeId(&mut name.0)).unwrap()) + BnString::from_raw( + NonNull::new(BNGenerateAutoDemangledTypeId(name.as_raw_mut())).unwrap(), + ) } } } @@ -2202,7 +2204,7 @@ impl Drop for InheritedStructureMember { } impl CoreArrayProvider for InheritedStructureMember { - type Raw = BNInheritedStructureMember ; + type Raw = BNInheritedStructureMember; type Context = (); type Wrapped<'a> = &'a Self; } @@ -2279,7 +2281,7 @@ impl NamedTypeReference { let result = BNCreateNamedType( type_class, ptr::null(), - &name.0 as *const _ as *mut BNQualifiedName, + name.as_raw() as *const BNQualifiedName as *mut BNQualifiedName, ); Self::from_raw(NonNull::new(result).unwrap()) } @@ -2301,15 +2303,14 @@ impl NamedTypeReference { let result = BNCreateNamedType( type_class, type_id.as_ref().as_ptr() as _, - &name.0 as *const _ as *mut BNQualifiedName, + name.as_raw() as *const BNQualifiedName as *mut BNQualifiedName, ); Self::from_raw(NonNull::new(result).unwrap()) } } pub fn name(&self) -> QualifiedName { - let named_ref: BNQualifiedName = unsafe { BNGetTypeReferenceName(self.as_raw()) }; - QualifiedName(named_ref) + unsafe { QualifiedName::from_raw(BNGetTypeReferenceName(self.as_raw())) } } pub fn id(&self) -> BnString { @@ -2369,9 +2370,34 @@ impl Debug for NamedTypeReference { // QualifiedName #[repr(C)] -pub struct QualifiedName(BNQualifiedName); +pub struct QualifiedName { + name: *mut BnString, + join: ManuallyDrop, + name_count: usize, +} impl QualifiedName { + pub fn new(names: N, join: J) -> Self + where + N: IntoIterator, + N::Item: BnStrCompatible, + J: BnStrCompatible, + { + let join = BnString::new(join); + let names: Vec<_> = names.into_iter().map(|n| n.into_bytes_with_nul()).collect(); + let mut names_ptr: Vec<*const core::ffi::c_char> = names + .iter() + .map(|n| n.as_ref().as_ptr() as *const core::ffi::c_char) + .collect(); + let names_list_ptr = names_ptr.as_mut_slice().as_mut_ptr(); + + QualifiedName { + name: unsafe { mem::transmute(BNAllocStringList(names_list_ptr, names.len())) }, + join: ManuallyDrop::new(join), + name_count: 1, + } + } + pub(crate) unsafe fn from_raw(handle: BNQualifiedName) -> Self { mem::transmute(handle) } @@ -2381,87 +2407,66 @@ impl QualifiedName { } pub(crate) fn as_raw(&self) -> &BNQualifiedName { - &self.0 + unsafe { mem::transmute(self) } } pub(crate) fn as_raw_mut(&mut self) -> &mut BNQualifiedName { - &mut self.0 + unsafe { mem::transmute(self) } } // TODO : I think this is bad pub fn string(&self) -> String { - unsafe { - slice::from_raw_parts(self.0.name, self.0.nameCount) - .iter() - .map(|c| CStr::from_ptr(*c).to_string_lossy()) - .collect::>() - .join("::") - } + self.strings() + .iter() + .map(|c| c.as_str()) + .collect::>() + .join("::") } - pub fn join(&self) -> Cow { - let join: *mut c_char = self.0.join; - unsafe { CStr::from_ptr(join) }.to_string_lossy() + pub fn join(&self) -> &str { + self.join.as_str() } - pub fn strings(&self) -> Vec> { - let names: *mut *mut c_char = self.0.name; - unsafe { - slice::from_raw_parts(names, self.0.nameCount) - .iter() - .map(|name| CStr::from_ptr(*name).to_string_lossy()) - .collect::>() - } + pub fn strings(&self) -> &[BnString] { + unsafe { slice::from_raw_parts(self.name, self.name_count) } } pub fn len(&self) -> usize { - self.0.nameCount + self.name_count } pub fn is_empty(&self) -> bool { - self.0.nameCount == 0 + self.len() == 0 } } impl From for QualifiedName { fn from(name: S) -> Self { - let join = BnString::new("::"); - let name = name.into_bytes_with_nul(); - let mut list = vec![name.as_ref().as_ptr() as *const _]; - - QualifiedName(BNQualifiedName { - name: unsafe { BNAllocStringList(list.as_mut_ptr(), 1) }, - join: join.into_raw(), - nameCount: 1, - }) + Some(name).into_iter().collect() } } -impl From> for QualifiedName { - fn from(names: Vec) -> Self { - let join = BnString::new("::"); - let names = names - .into_iter() - .map(|n| n.into_bytes_with_nul()) - .collect::>(); - let mut list = names - .iter() - .map(|n| n.as_ref().as_ptr() as *const _) - .collect::>(); - - QualifiedName(BNQualifiedName { - name: unsafe { BNAllocStringList(list.as_mut_ptr(), list.len()) }, - join: join.into_raw(), - nameCount: list.len(), - }) +impl FromIterator for QualifiedName { + fn from_iter>(iter: T) -> Self { + let default_join = unsafe { CStr::from_bytes_with_nul_unchecked(b"::\x00") }; + Self::new(iter, default_join) } } impl Clone for QualifiedName { fn clone(&self) -> Self { - let strings = self.strings(); - let name = Self::from(strings.iter().collect::>>()); - name + let name_raw = unsafe { + BNAllocStringList( + self.as_raw().name as *mut *const core::ffi::c_char, + self.name_count, + ) + }; + let name = unsafe { mem::transmute(name_raw) }; + Self { + name, + join: self.join.clone(), + name_count: self.name_count, + } } } @@ -2494,9 +2499,7 @@ impl Eq for QualifiedName {} impl Drop for QualifiedName { fn drop(&mut self) { - unsafe { - BNFreeQualifiedName(&mut self.0); - } + unsafe { BNFreeQualifiedName(self.as_raw_mut()) }; } } From dae5412c17f5141afa1aca941578429fa3e0be8f Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Thu, 30 May 2024 09:54:04 -0300 Subject: [PATCH 23/33] change `RegisterValue` to the new standard --- rust/src/function.rs | 3 +- rust/src/hlil/instruction.rs | 14 ++-- rust/src/mlil/instruction.rs | 16 ++--- rust/src/types.rs | 135 +++++++++++++---------------------- 4 files changed, 66 insertions(+), 102 deletions(-) diff --git a/rust/src/function.rs b/rust/src/function.rs index 29edb15ee..ec9c5a3e2 100644 --- a/rust/src/function.rs +++ b/rust/src/function.rs @@ -1205,8 +1205,7 @@ impl Function { size: Option, ) -> DataBuffer { let size = size.unwrap_or(0); - let state_raw = state.into_raw_value(); - DataBuffer::from_raw(unsafe { BNGetConstantData(self.handle, state_raw, value, size) }) + DataBuffer::from_raw(unsafe { BNGetConstantData(self.handle, state, value, size) }) } pub fn constants_referenced_by( diff --git a/rust/src/hlil/instruction.rs b/rust/src/hlil/instruction.rs index 6b27284d4..125a060b5 100644 --- a/rust/src/hlil/instruction.rs +++ b/rust/src/hlil/instruction.rs @@ -4,7 +4,7 @@ use binaryninjacore_sys::BNHighLevelILOperation; use crate::architecture::CoreIntrinsic; use crate::operand_iter::OperandIter; use crate::rc::Ref; -use crate::types::{ConstantData, RegisterValue, RegisterValueType, SSAVariable, Variable}; +use crate::types::{ConstantData, RegisterValue, SSAVariable, Variable}; use super::operation::*; use super::{HighLevelILFunction, HighLevelILLiftedInstruction, HighLevelILLiftedInstructionKind}; @@ -749,12 +749,12 @@ impl HighLevelILInstruction { ConstData(op) => Lifted::ConstData(LiftedConstData { constant_data: ConstantData::new( self.function.get_function(), - RegisterValue { - state: RegisterValueType::from_raw_value(op.constant_data_kind).unwrap(), - value: op.constant_data_value, - offset: 0, - size: op.size, - }, + RegisterValue::new( + RegisterValue::type_from_u32(op.constant_data_kind).unwrap(), + op.constant_data_value, + 0, + op.size, + ), ), }), diff --git a/rust/src/mlil/instruction.rs b/rust/src/mlil/instruction.rs index c9f102b48..a0db9a103 100644 --- a/rust/src/mlil/instruction.rs +++ b/rust/src/mlil/instruction.rs @@ -7,8 +7,8 @@ use crate::disassembly::InstructionTextToken; use crate::operand_iter::OperandIter; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref}; use crate::types::{ - Conf, ConstantData, DataFlowQueryOption, ILBranchDependence, PossibleValueSet, - RegisterValue, RegisterValueType, SSAVariable, Type, Variable, + Conf, ConstantData, DataFlowQueryOption, ILBranchDependence, PossibleValueSet, RegisterValue, + SSAVariable, Type, Variable, }; use super::lift::*; @@ -751,12 +751,12 @@ impl MediumLevelILInstruction { ConstData(op) => Lifted::ConstData(LiftedConstData { constant_data: ConstantData::new( self.function.get_function(), - RegisterValue { - state: RegisterValueType::from_raw_value(op.constant_data_kind).unwrap(), - value: op.constant_data_value, - offset: 0, - size: op.size, - }, + RegisterValue::new( + RegisterValue::type_from_u32(op.constant_data_kind).unwrap(), + op.constant_data_value, + 0, + op.size, + ), ), }), Jump(op) => Lifted::Jump(LiftedJump { diff --git a/rust/src/types.rs b/rust/src/types.rs index a131e1780..ebef3a54b 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -2859,85 +2859,18 @@ unsafe impl CoreArrayProviderInner for DataVariableAndNameAndDebugParser { ///////////////////////// // RegisterValueType -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub enum RegisterValueType { - UndeterminedValue, - EntryValue, - ConstantValue, - ConstantPointerValue, - ExternalPointerValue, - StackFrameOffset, - ReturnAddressValue, - ImportedAddressValue, - SignedRangeValue, - UnsignedRangeValue, - LookupTableValue, - InSetOfValues, - NotInSetOfValues, - ConstantDataValue, - ConstantDataZeroExtendValue, - ConstantDataSignExtendValue, - ConstantDataAggregateValue, -} - -impl RegisterValueType { - pub(crate) fn from_raw_value(value: u32) -> Option { - use BNRegisterValueType::*; - Some(match value { - x if x == UndeterminedValue as u32 => Self::UndeterminedValue, - x if x == EntryValue as u32 => Self::EntryValue, - x if x == ConstantValue as u32 => Self::ConstantValue, - x if x == ConstantPointerValue as u32 => Self::ConstantPointerValue, - x if x == ExternalPointerValue as u32 => Self::ExternalPointerValue, - x if x == StackFrameOffset as u32 => Self::StackFrameOffset, - x if x == ReturnAddressValue as u32 => Self::ReturnAddressValue, - x if x == ImportedAddressValue as u32 => Self::ImportedAddressValue, - x if x == SignedRangeValue as u32 => Self::SignedRangeValue, - x if x == UnsignedRangeValue as u32 => Self::UnsignedRangeValue, - x if x == LookupTableValue as u32 => Self::LookupTableValue, - x if x == InSetOfValues as u32 => Self::InSetOfValues, - x if x == NotInSetOfValues as u32 => Self::NotInSetOfValues, - x if x == ConstantDataValue as u32 => Self::ConstantDataValue, - x if x == ConstantDataZeroExtendValue as u32 => Self::ConstantDataZeroExtendValue, - x if x == ConstantDataSignExtendValue as u32 => Self::ConstantDataSignExtendValue, - x if x == ConstantDataAggregateValue as u32 => Self::ConstantDataAggregateValue, - _ => return None, - }) - } - - pub(crate) fn into_raw_value(self) -> BNRegisterValueType { - use BNRegisterValueType::*; - match self { - Self::UndeterminedValue => UndeterminedValue, - Self::EntryValue => EntryValue, - Self::ConstantValue => ConstantValue, - Self::ConstantPointerValue => ConstantPointerValue, - Self::ExternalPointerValue => ExternalPointerValue, - Self::StackFrameOffset => StackFrameOffset, - Self::ReturnAddressValue => ReturnAddressValue, - Self::ImportedAddressValue => ImportedAddressValue, - Self::SignedRangeValue => SignedRangeValue, - Self::UnsignedRangeValue => UnsignedRangeValue, - Self::LookupTableValue => LookupTableValue, - Self::InSetOfValues => InSetOfValues, - Self::NotInSetOfValues => NotInSetOfValues, - Self::ConstantDataValue => ConstantDataValue, - Self::ConstantDataZeroExtendValue => ConstantDataZeroExtendValue, - Self::ConstantDataSignExtendValue => ConstantDataSignExtendValue, - Self::ConstantDataAggregateValue => ConstantDataAggregateValue, - } - } -} +pub type RegisterValueType = BNRegisterValueType; ///////////////////////// // RegisterValue +#[repr(C)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct RegisterValue { - pub(crate) state: RegisterValueType, - pub(crate) value: i64, - pub(crate) offset: i64, - pub(crate) size: usize, + pub state: RegisterValueType, + pub value: i64, + pub offset: i64, + pub size: usize, } impl RegisterValue { @@ -2949,27 +2882,59 @@ impl RegisterValue { size, } } -} -impl From for RegisterValue { - fn from(value: BNRegisterValue) -> Self { + pub(crate) fn type_from_u32(raw_type: u32) -> Option { + use BNRegisterValueType::*; + Some(match raw_type { + 0 => UndeterminedValue, + 1 => EntryValue, + 2 => ConstantValue, + 3 => ConstantPointerValue, + 4 => ExternalPointerValue, + 5 => StackFrameOffset, + 6 => ReturnAddressValue, + 7 => ImportedAddressValue, + 8 => SignedRangeValue, + 9 => UnsignedRangeValue, + 10 => LookupTableValue, + 11 => InSetOfValues, + 12 => NotInSetOfValues, + 32768 => ConstantDataValue, + 32769 => ConstantDataZeroExtendValue, + 32770 => ConstantDataSignExtendValue, + 32771 => ConstantDataAggregateValue, + _ => return None, + }) + } + + pub(crate) fn from_raw(value: BNRegisterValue) -> Self { Self { - state: RegisterValueType::from_raw_value(value.state as u32).unwrap(), + state: value.state, value: value.value, offset: value.offset, size: value.size, } } + + pub(crate) fn raw(self) -> BNRegisterValue { + BNRegisterValue { + state: self.state, + value: self.value, + offset: self.offset, + size: self.size, + } + } +} + +impl From for RegisterValue { + fn from(value: BNRegisterValue) -> Self { + Self::from_raw(value) + } } impl From for BNRegisterValue { fn from(value: RegisterValue) -> Self { - Self { - state: value.state.into_raw_value(), - value: value.value, - offset: value.offset, - size: value.size, - } + value.raw() } } @@ -3176,7 +3141,7 @@ impl PossibleValueSet { pub(crate) fn into_raw(self) -> PossibleValueSetRaw { let mut raw: BNPossibleValueSet = unsafe { core::mem::zeroed() }; // set the state field - raw.state = self.value_type().into_raw_value(); + raw.state = self.value_type(); // set all other fields match self { PossibleValueSet::UndeterminedValue @@ -3217,7 +3182,7 @@ impl PossibleValueSet { } pub fn value_type(&self) -> RegisterValueType { - use RegisterValueType::*; + use BNRegisterValueType::*; match self { PossibleValueSet::UndeterminedValue => UndeterminedValue, PossibleValueSet::EntryValue { .. } => EntryValue, From dc96bff8a37edc0fd5a6d884597dd359499db51c Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Thu, 30 May 2024 12:40:33 -0300 Subject: [PATCH 24/33] change `Architecture` to the new standard --- rust/src/architecture.rs | 69 +++++++++++----------------------------- rust/src/types.rs | 32 ++++++++++++++++--- 2 files changed, 47 insertions(+), 54 deletions(-) diff --git a/rust/src/architecture.rs b/rust/src/architecture.rs index d6f11f381..a716fd4da 100644 --- a/rust/src/architecture.rs +++ b/rust/src/architecture.rs @@ -316,7 +316,7 @@ pub trait Intrinsic: Sized + Clone + Copy { fn inputs(&self) -> Array; /// Returns the list of the output types for this intrinsic. - fn outputs(&self) -> Vec>; + fn outputs(&self) -> Array>; } pub trait Architecture: 'static + Sized + AsRef { @@ -356,7 +356,7 @@ pub trait Architecture: 'static + Sized + AsRef { &self, data: &[u8], addr: u64, - ) -> Option<(usize, Vec)>; + ) -> Option<(usize, Array)>; fn instruction_llil( &self, data: &[u8], @@ -653,7 +653,7 @@ impl Intrinsic for UnusedIntrinsic { fn inputs(&self) -> Array { unreachable!() } - fn outputs(&self) -> Vec> { + fn outputs(&self) -> Array> { unreachable!() } } @@ -1009,28 +1009,14 @@ impl Intrinsic for crate::architecture::CoreIntrinsic { fn inputs(&self) -> Array { let mut count: usize = 0; - - unsafe { - let inputs = BNGetArchitectureIntrinsicInputs(self.0, self.1, &mut count as *mut _); - Array::new(inputs, count, ()) - } + let inputs = unsafe { BNGetArchitectureIntrinsicInputs(self.0, self.1, &mut count) }; + unsafe { Array::new(inputs, count, ()) } } - fn outputs(&self) -> Vec> { + fn outputs(&self) -> Array> { let mut count: usize = 0; - - unsafe { - let inputs = BNGetArchitectureIntrinsicOutputs(self.0, self.1, &mut count as *mut _); - - let ret = slice::from_raw_parts_mut(inputs, count) - .iter() - .map(|input| (*input).into()) - .collect(); - - BNFreeOutputTypeList(inputs, count); - - ret - } + let inputs = unsafe { BNGetArchitectureIntrinsicOutputs(self.0, self.1, &mut count) }; + unsafe { Array::new(inputs, count, ()) } } } @@ -1155,7 +1141,7 @@ impl Architecture for CoreArchitecture { &self, data: &[u8], addr: u64, - ) -> Option<(usize, Vec)> { + ) -> Option<(usize, Array)> { let mut consumed = data.len(); let mut count: usize = 0; let mut result: *mut BNInstructionTextToken = ptr::null_mut(); @@ -1169,12 +1155,8 @@ impl Architecture for CoreArchitecture { &mut result as *mut _, &mut count as *mut _, ) { - let vec = slice::from_raw_parts(result, count) - .iter() - .map(|x| InstructionTextToken::from_raw(x).to_owned()) - .collect(); - BNFreeInstructionText(result, count); - Some((consumed, vec)) + let array = Array::new(result, count, ()); + Some((consumed, array)) } else { None } @@ -1822,13 +1804,10 @@ where return false; }; - let res_tokens: Box<[_]> = res_tokens.into_boxed_slice(); unsafe { - let res_tokens = Box::leak(res_tokens); - let r_ptr = res_tokens.as_mut_ptr(); - let r_count = res_tokens.len(); + let (r_ptr, r_count, ()) = res_tokens.into_raw(); - *result = &mut (*r_ptr).0; + *result = r_ptr; *count = r_count; *len = res_size; } @@ -1836,7 +1815,7 @@ where } extern "C" fn cb_free_instruction_text(tokens: *mut BNInstructionTextToken, count: usize) { - let _tokens = unsafe { Box::from_raw(ptr::slice_from_raw_parts_mut(tokens, count)) }; + let _tokens: Array = unsafe { Array::new(tokens, count, ()) }; } extern "C" fn cb_instruction_llil( @@ -2455,22 +2434,12 @@ where if let Some(intrinsic) = custom_arch.intrinsic_from_id(intrinsic) { let inputs = intrinsic.outputs(); - let mut res: Box<[_]> = inputs.iter().map(|input| input.as_ref().into()).collect(); - unsafe { - *count = res.len(); - if res.is_empty() { - ptr::null_mut() - } else { - let raw = res.as_mut_ptr(); - mem::forget(res); - raw - } - } + let (i_ptr, i_count, _i_context) = unsafe { inputs.into_raw() }; + unsafe { *count = i_count }; + i_ptr } else { - unsafe { - *count = 0; - } + unsafe { *count = 0 }; ptr::null_mut() } } @@ -2484,7 +2453,7 @@ where { let _custom_arch = unsafe { &*(ctxt as *mut A) }; if !tl.is_null() { - let _type_list = unsafe { Box::from_raw(ptr::slice_from_raw_parts_mut(tl, count)) }; + let _type_array: Array> = unsafe { Array::new(tl, count, ()) }; } } diff --git a/rust/src/types.rs b/rust/src/types.rs index ebef3a54b..eb306d2ec 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -707,6 +707,10 @@ pub struct Type { /// bv.define_user_type("int_2", &my_custom_type_2); /// ``` impl Type { + pub(crate) unsafe fn ref_from_raw(handle: &*mut BNType) -> &Self { + mem::transmute(handle) + } + pub(crate) unsafe fn from_raw(handle: NonNull) -> Self { Self { handle } } @@ -1254,6 +1258,22 @@ impl Drop for Type { } } +impl CoreArrayProvider for Conf { + type Raw = BNTypeWithConfidence; + type Context = (); + type Wrapped<'a> = Conf<&'a Type>; +} + +unsafe impl CoreArrayProviderInner for Conf { + unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) { + BNFreeOutputTypeList(raw, count); + } + + unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> { + Conf::new(Type::ref_from_raw(&raw.type_), raw.confidence) + } +} + /////////////////////// // FunctionParameter @@ -3793,7 +3813,7 @@ unsafe impl CoreArrayProviderInner for UnresolvedIndirectBranches { mod test { use crate::types::{FunctionParameter, TypeClass}; - use super::{Type, TypeBuilder}; + use super::{NamedTypeReference, NamedTypeReferenceClass, QualifiedName, Type, TypeBuilder}; #[test] fn create_bool_type() { @@ -3832,9 +3852,13 @@ mod test { assert_eq!(type_built, expected_type); } - // TODO NamedTypeReference::new, NamedTypeReference::new_with_id was - // previously leaking memory, probably because the name received a ownership - // and didn't clone it, please verify the fix + #[test] + fn create_name_type_reference() { + let name: QualifiedName = "Test".into(); + let type_class = NamedTypeReferenceClass::UnknownNamedTypeClass; + let name_type_ref = NamedTypeReference::new(type_class, &name); + assert_eq!(name_type_ref.name().string().as_str(), "Test"); + } // TODO ::parse_types_from_source forgot to call // BNFreeTypeParserResult, leaking the result From 818e335bf6ad8515175956b8ab4a119d3454a565 Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Thu, 30 May 2024 13:02:04 -0300 Subject: [PATCH 25/33] fix mem leak at `Platform::parse_types_from_source` --- rust/src/platform.rs | 32 +++++++++++++++----------------- rust/src/types.rs | 3 --- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/rust/src/platform.rs b/rust/src/platform.rs index ccad41a27..8b1e7c4a3 100644 --- a/rust/src/platform.rs +++ b/rust/src/platform.rs @@ -313,35 +313,33 @@ impl TypeParser for Platform { auto_type_source.as_ref().as_ptr() as _, ); - let error_msg = BnString::from_raw(NonNull::new(error_string).unwrap()); - if !success { + let error_msg = BnString::from_raw(NonNull::new(error_string).unwrap()); return Err(error_msg.to_string()); } for i in slice::from_raw_parts(result.types, result.typeCount) { - let name = QualifiedName::from_raw(i.name); - type_parser_result.types.insert( - name.string(), - Type::from_raw(ptr::NonNull::new(i.type_).unwrap()), - ); + let name = QualifiedName::ref_from_raw(&i.name); + type_parser_result + .types + .insert(name.string(), Type::ref_from_raw(&i.type_).clone()); } for i in slice::from_raw_parts(result.functions, result.functionCount) { - let name = QualifiedName::from_raw(i.name); - type_parser_result.functions.insert( - name.string(), - Type::from_raw(ptr::NonNull::new(i.type_).unwrap()), - ); + let name = QualifiedName::ref_from_raw(&i.name); + type_parser_result + .functions + .insert(name.string(), Type::ref_from_raw(&i.type_).clone()); } for i in slice::from_raw_parts(result.variables, result.variableCount) { - let name = QualifiedName::from_raw(i.name); - type_parser_result.variables.insert( - name.string(), - Type::from_raw(ptr::NonNull::new(i.type_).unwrap()), - ); + let name = QualifiedName::ref_from_raw(&i.name); + type_parser_result + .variables + .insert(name.string(), Type::ref_from_raw(&i.type_).clone()); } + + BNFreeTypeParserResult(&mut result); } Ok(type_parser_result) diff --git a/rust/src/types.rs b/rust/src/types.rs index eb306d2ec..34b53d88d 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -3860,9 +3860,6 @@ mod test { assert_eq!(name_type_ref.name().string().as_str(), "Test"); } - // TODO ::parse_types_from_source forgot to call - // BNFreeTypeParserResult, leaking the result - // TODO BNGetDebugDataVariableByName returns a *mut BNDataVariableAndName // pointer, can we deref it? Or it need to be freed by proper drop. // Verify if From 75e6d1d8ab1f3b3a54bb0cc45a80a04e7cdcffc2 Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Thu, 30 May 2024 13:05:00 -0300 Subject: [PATCH 26/33] don't consume the parameter at --- rust/src/debuginfo.rs | 2 +- rust/src/types.rs | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/rust/src/debuginfo.rs b/rust/src/debuginfo.rs index f539fd904..7288d4696 100644 --- a/rust/src/debuginfo.rs +++ b/rust/src/debuginfo.rs @@ -778,7 +778,7 @@ impl DebugInfo { } } - pub fn add_data_variable_info(&self, var: DataVariableAndName) -> bool { + pub fn add_data_variable_info(&self, var: &DataVariableAndName) -> bool { unsafe { BNAddDebugDataVariableInfo(self.handle, var.as_raw()) } } } diff --git a/rust/src/types.rs b/rust/src/types.rs index 34b53d88d..e25401f94 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -3859,14 +3859,4 @@ mod test { let name_type_ref = NamedTypeReference::new(type_class, &name); assert_eq!(name_type_ref.name().string().as_str(), "Test"); } - - // TODO BNGetDebugDataVariableByName returns a *mut BNDataVariableAndName - // pointer, can we deref it? Or it need to be freed by proper drop. - // Verify if - // * DebugInfo::get_data_variable_by_name - // * DebugInfo::get_data_variable_by_address - // should call BNFreeDataVariableAndName - // Also verify if - // * DebugInfo::add_data_variable_info - // should receive a reference or some kind of owned pointer } From 25f3dc567f97627a14750ece19b5bff6576e4bd1 Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Thu, 30 May 2024 14:12:32 -0300 Subject: [PATCH 27/33] Revert "change `Architecture` to the new standard" This reverts commit dc96bff8a37edc0fd5a6d884597dd359499db51c. --- rust/src/architecture.rs | 69 +++++++++++++++++++++++++++++----------- rust/src/types.rs | 26 +++------------ 2 files changed, 54 insertions(+), 41 deletions(-) diff --git a/rust/src/architecture.rs b/rust/src/architecture.rs index a716fd4da..d6f11f381 100644 --- a/rust/src/architecture.rs +++ b/rust/src/architecture.rs @@ -316,7 +316,7 @@ pub trait Intrinsic: Sized + Clone + Copy { fn inputs(&self) -> Array; /// Returns the list of the output types for this intrinsic. - fn outputs(&self) -> Array>; + fn outputs(&self) -> Vec>; } pub trait Architecture: 'static + Sized + AsRef { @@ -356,7 +356,7 @@ pub trait Architecture: 'static + Sized + AsRef { &self, data: &[u8], addr: u64, - ) -> Option<(usize, Array)>; + ) -> Option<(usize, Vec)>; fn instruction_llil( &self, data: &[u8], @@ -653,7 +653,7 @@ impl Intrinsic for UnusedIntrinsic { fn inputs(&self) -> Array { unreachable!() } - fn outputs(&self) -> Array> { + fn outputs(&self) -> Vec> { unreachable!() } } @@ -1009,14 +1009,28 @@ impl Intrinsic for crate::architecture::CoreIntrinsic { fn inputs(&self) -> Array { let mut count: usize = 0; - let inputs = unsafe { BNGetArchitectureIntrinsicInputs(self.0, self.1, &mut count) }; - unsafe { Array::new(inputs, count, ()) } + + unsafe { + let inputs = BNGetArchitectureIntrinsicInputs(self.0, self.1, &mut count as *mut _); + Array::new(inputs, count, ()) + } } - fn outputs(&self) -> Array> { + fn outputs(&self) -> Vec> { let mut count: usize = 0; - let inputs = unsafe { BNGetArchitectureIntrinsicOutputs(self.0, self.1, &mut count) }; - unsafe { Array::new(inputs, count, ()) } + + unsafe { + let inputs = BNGetArchitectureIntrinsicOutputs(self.0, self.1, &mut count as *mut _); + + let ret = slice::from_raw_parts_mut(inputs, count) + .iter() + .map(|input| (*input).into()) + .collect(); + + BNFreeOutputTypeList(inputs, count); + + ret + } } } @@ -1141,7 +1155,7 @@ impl Architecture for CoreArchitecture { &self, data: &[u8], addr: u64, - ) -> Option<(usize, Array)> { + ) -> Option<(usize, Vec)> { let mut consumed = data.len(); let mut count: usize = 0; let mut result: *mut BNInstructionTextToken = ptr::null_mut(); @@ -1155,8 +1169,12 @@ impl Architecture for CoreArchitecture { &mut result as *mut _, &mut count as *mut _, ) { - let array = Array::new(result, count, ()); - Some((consumed, array)) + let vec = slice::from_raw_parts(result, count) + .iter() + .map(|x| InstructionTextToken::from_raw(x).to_owned()) + .collect(); + BNFreeInstructionText(result, count); + Some((consumed, vec)) } else { None } @@ -1804,10 +1822,13 @@ where return false; }; + let res_tokens: Box<[_]> = res_tokens.into_boxed_slice(); unsafe { - let (r_ptr, r_count, ()) = res_tokens.into_raw(); + let res_tokens = Box::leak(res_tokens); + let r_ptr = res_tokens.as_mut_ptr(); + let r_count = res_tokens.len(); - *result = r_ptr; + *result = &mut (*r_ptr).0; *count = r_count; *len = res_size; } @@ -1815,7 +1836,7 @@ where } extern "C" fn cb_free_instruction_text(tokens: *mut BNInstructionTextToken, count: usize) { - let _tokens: Array = unsafe { Array::new(tokens, count, ()) }; + let _tokens = unsafe { Box::from_raw(ptr::slice_from_raw_parts_mut(tokens, count)) }; } extern "C" fn cb_instruction_llil( @@ -2434,12 +2455,22 @@ where if let Some(intrinsic) = custom_arch.intrinsic_from_id(intrinsic) { let inputs = intrinsic.outputs(); + let mut res: Box<[_]> = inputs.iter().map(|input| input.as_ref().into()).collect(); - let (i_ptr, i_count, _i_context) = unsafe { inputs.into_raw() }; - unsafe { *count = i_count }; - i_ptr + unsafe { + *count = res.len(); + if res.is_empty() { + ptr::null_mut() + } else { + let raw = res.as_mut_ptr(); + mem::forget(res); + raw + } + } } else { - unsafe { *count = 0 }; + unsafe { + *count = 0; + } ptr::null_mut() } } @@ -2453,7 +2484,7 @@ where { let _custom_arch = unsafe { &*(ctxt as *mut A) }; if !tl.is_null() { - let _type_array: Array> = unsafe { Array::new(tl, count, ()) }; + let _type_list = unsafe { Box::from_raw(ptr::slice_from_raw_parts_mut(tl, count)) }; } } diff --git a/rust/src/types.rs b/rust/src/types.rs index e25401f94..6790a159f 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -707,10 +707,6 @@ pub struct Type { /// bv.define_user_type("int_2", &my_custom_type_2); /// ``` impl Type { - pub(crate) unsafe fn ref_from_raw(handle: &*mut BNType) -> &Self { - mem::transmute(handle) - } - pub(crate) unsafe fn from_raw(handle: NonNull) -> Self { Self { handle } } @@ -1258,22 +1254,6 @@ impl Drop for Type { } } -impl CoreArrayProvider for Conf { - type Raw = BNTypeWithConfidence; - type Context = (); - type Wrapped<'a> = Conf<&'a Type>; -} - -unsafe impl CoreArrayProviderInner for Conf { - unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) { - BNFreeOutputTypeList(raw, count); - } - - unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> { - Conf::new(Type::ref_from_raw(&raw.type_), raw.confidence) - } -} - /////////////////////// // FunctionParameter @@ -3811,9 +3791,11 @@ unsafe impl CoreArrayProviderInner for UnresolvedIndirectBranches { #[cfg(test)] mod test { - use crate::types::{FunctionParameter, TypeClass}; + use crate::types::{ + FunctionParameter, NamedTypeReference, NamedTypeReferenceClass, QualifiedName, TypeClass, + }; - use super::{NamedTypeReference, NamedTypeReferenceClass, QualifiedName, Type, TypeBuilder}; + use super::{Type, TypeBuilder}; #[test] fn create_bool_type() { From f7ca88baebbdf3f94160c41a8de19000da113166 Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Thu, 30 May 2024 14:30:30 -0300 Subject: [PATCH 28/33] fix examples --- arch/riscv/src/lib.rs | 23 ++- rust/examples/dwarf/dwarf_export/src/lib.rs | 33 ++-- .../dwarf/dwarf_import/src/die_handlers.rs | 51 ++--- .../dwarf/dwarf_import/src/dwarfdebuginfo.rs | 10 +- rust/examples/dwarf/dwarf_import/src/types.rs | 13 +- rust/examples/pdb-ng/src/parser.rs | 43 ++--- rust/examples/pdb-ng/src/struct_grouper.rs | 4 +- rust/examples/pdb-ng/src/symbol_parser.rs | 92 +++++---- rust/examples/pdb-ng/src/type_parser.rs | 179 ++++++++---------- rust/src/architecture.rs | 31 ++- rust/src/binaryview.rs | 2 +- rust/src/function.rs | 12 +- rust/src/mlil/instruction.rs | 2 +- rust/src/rc.rs | 12 -- rust/src/types.rs | 82 ++++++-- 15 files changed, 306 insertions(+), 283 deletions(-) diff --git a/arch/riscv/src/lib.rs b/arch/riscv/src/lib.rs index bc67e4655..f4c0118b8 100644 --- a/arch/riscv/src/lib.rs +++ b/arch/riscv/src/lib.rs @@ -29,7 +29,6 @@ use binaryninja::{ ExprInfo, InstrInfo, Label, Liftable, LiftableWithSize, LiftedNonSSA, Lifter, Mutable, NonSSA, }, - rc::Ref, relocation::{ CoreRelocationHandler, CustomRelocationHandlerHandle, RelocationHandler, RelocationInfo, RelocationType, @@ -508,7 +507,7 @@ impl architecture::Intrinsic for RiscVIntrinsic { } } - fn inputs(&self) -> Vec> { + fn inputs(&self) -> Vec { match self.id { Intrinsic::Uret | Intrinsic::Sret | Intrinsic::Mret | Intrinsic::Wfi => { vec![] @@ -516,16 +515,16 @@ impl architecture::Intrinsic for RiscVIntrinsic { Intrinsic::Csrrd => { vec![NameAndType::new( "csr", - &Type::int(4, false), + Type::int(4, false), max_confidence(), )] } Intrinsic::Csrrw | Intrinsic::Csrwr | Intrinsic::Csrrs | Intrinsic::Csrrc => { vec![ - NameAndType::new("csr", &Type::int(4, false), max_confidence()), + NameAndType::new("csr", Type::int(4, false), max_confidence()), NameAndType::new( "value", - &Type::int(::Int::width(), false), + Type::int(::Int::width(), false), min_confidence(), ), ] @@ -540,8 +539,8 @@ impl architecture::Intrinsic for RiscVIntrinsic { | Intrinsic::Fmin(size) | Intrinsic::Fmax(size) => { vec![ - NameAndType::new("", &Type::float(size as usize), max_confidence()), - NameAndType::new("", &Type::float(size as usize), max_confidence()), + NameAndType::new("", Type::float(size as usize), max_confidence()), + NameAndType::new("", Type::float(size as usize), max_confidence()), ] } Intrinsic::Fsqrt(size, _) @@ -551,35 +550,35 @@ impl architecture::Intrinsic for RiscVIntrinsic { | Intrinsic::FcvtFToU(size, _, _) => { vec![NameAndType::new( "", - &Type::float(size as usize), + Type::float(size as usize), max_confidence(), )] } Intrinsic::FcvtIToF(size, _, _) => { vec![NameAndType::new( "", - &Type::int(size as usize, true), + Type::int(size as usize, true), max_confidence(), )] } Intrinsic::FcvtUToF(size, _, _) => { vec![NameAndType::new( "", - &Type::int(size as usize, false), + Type::int(size as usize, false), max_confidence(), )] } Intrinsic::Fence => { vec![NameAndType::new( "", - &Type::int(4, false), + Type::int(4, false), min_confidence(), )] } } } - fn outputs(&self) -> Vec>> { + fn outputs(&self) -> Vec> { match self.id { Intrinsic::Uret | Intrinsic::Sret diff --git a/rust/examples/dwarf/dwarf_export/src/lib.rs b/rust/examples/dwarf/dwarf_export/src/lib.rs index 057abe27d..02f2a360d 100644 --- a/rust/examples/dwarf/dwarf_export/src/lib.rs +++ b/rust/examples/dwarf/dwarf_export/src/lib.rs @@ -16,7 +16,6 @@ use binaryninja::{ interaction, interaction::{FormResponses, FormResponses::Index}, logger::init, - rc::Ref, string::BnString, symbol::SymbolType, types::{Conf, MemberAccess, StructureType, Type, TypeClass}, @@ -27,12 +26,12 @@ fn export_type( name: String, t: &Type, bv: &BinaryView, - defined_types: &mut Vec<(Ref, UnitEntryId)>, + defined_types: &mut Vec<(Type, UnitEntryId)>, dwarf: &mut DwarfUnit, ) -> Option { if let Some((_, die)) = defined_types .iter() - .find(|(defined_type, _)| defined_type.as_ref() == t) + .find(|(defined_type, _)| defined_type == t) { return Some(*die); } @@ -130,12 +129,12 @@ fn export_type( AttributeValue::Data2(t.width() as u16), ); - for struct_member in t.get_structure().unwrap().members().unwrap() { + for struct_member in t.get_structure().unwrap().members().unwrap().iter() { let struct_member_die_uid = dwarf.unit.add(structure_die_uid, constants::DW_TAG_member); dwarf.unit.get_mut(struct_member_die_uid).set( gimli::DW_AT_name, - AttributeValue::String(struct_member.name.as_bytes().to_vec()), + AttributeValue::String(struct_member.name().as_bytes().to_vec()), ); match struct_member.access { MemberAccess::PrivateAccess => { @@ -164,8 +163,8 @@ fn export_type( ); if let Some(target_die_uid) = export_type( - format!("{}", struct_member.ty.contents), - struct_member.ty.contents.as_ref(), + format!("{}", struct_member.ty().contents), + struct_member.ty().contents, bv, defined_types, dwarf, @@ -192,7 +191,7 @@ fn export_type( AttributeValue::Data1(t.width() as u8), ); - for enum_field in t.get_enumeration().unwrap().members() { + for enum_field in t.get_enumeration().unwrap().members().iter() { let enum_field_die_uid = dwarf.unit.add(enum_die_uid, constants::DW_TAG_enumerator); dwarf.unit.get_mut(enum_field_die_uid).set( gimli::DW_AT_name, @@ -373,7 +372,7 @@ fn export_type( fn export_types( bv: &BinaryView, dwarf: &mut DwarfUnit, - defined_types: &mut Vec<(Ref, UnitEntryId)>, + defined_types: &mut Vec<(Type, UnitEntryId)>, ) { for t in &bv.types() { export_type( @@ -389,7 +388,7 @@ fn export_types( fn export_functions( bv: &BinaryView, dwarf: &mut DwarfUnit, - defined_types: &mut Vec<(Ref, UnitEntryId)>, + defined_types: &mut Vec<(Type, UnitEntryId)>, ) { let entry_point = bv.entry_point_function(); @@ -459,7 +458,7 @@ fn export_functions( if function.return_type().contents.type_class() != TypeClass::VoidTypeClass { if let Some(return_type_die_uid) = export_type( format!("{}", function.return_type().contents), - function.return_type().contents.as_ref(), + &function.return_type().contents, bv, defined_types, dwarf, @@ -471,19 +470,19 @@ fn export_functions( } } - for parameter in function.function_type().parameters().unwrap() { + for parameter in function.function_type().parameters().unwrap().iter() { let param_die_uid = dwarf .unit .add(function_die_uid, constants::DW_TAG_formal_parameter); dwarf.unit.get_mut(param_die_uid).set( gimli::DW_AT_name, - AttributeValue::String(parameter.name.as_bytes().to_vec()), + AttributeValue::String(parameter.name().as_bytes().to_vec()), ); if let Some(target_die_uid) = export_type( - format!("{}", parameter.t.contents), - ¶meter.t.contents, + format!("{}", ¶meter.t), + ¶meter.t, bv, defined_types, dwarf, @@ -516,7 +515,7 @@ fn export_functions( fn export_data_vars( bv: &BinaryView, dwarf: &mut DwarfUnit, - defined_types: &mut Vec<(Ref, UnitEntryId)>, + defined_types: &mut Vec<(Type, UnitEntryId)>, ) { let root = dwarf.unit.root(); @@ -754,7 +753,7 @@ fn export_dwarf(bv: &BinaryView) { ); // Everything has types, so we need to track what is already defined globally as to not duplicate type entries - let mut defined_types: Vec<(Ref, UnitEntryId)> = vec![]; + let mut defined_types: Vec<(Type, UnitEntryId)> = vec![]; export_types(bv, &mut dwarf, &mut defined_types); export_functions(bv, &mut dwarf, &mut defined_types); export_data_vars(bv, &mut dwarf, &mut defined_types); diff --git a/rust/examples/dwarf/dwarf_import/src/die_handlers.rs b/rust/examples/dwarf/dwarf_import/src/die_handlers.rs index bcc6be66e..b5534fb26 100644 --- a/rust/examples/dwarf/dwarf_import/src/die_handlers.rs +++ b/rust/examples/dwarf/dwarf_import/src/die_handlers.rs @@ -16,10 +16,7 @@ use crate::dwarfdebuginfo::{DebugInfoBuilder, DebugInfoBuilderContext, TypeUID}; use crate::helpers::*; use crate::types::get_type; -use binaryninja::{ - rc::*, - types::{EnumerationBuilder, FunctionParameter, ReferenceType, Type, TypeBuilder}, -}; +use binaryninja::types::{EnumerationBuilder, FunctionParameter, ReferenceType, Type, TypeBuilder}; use gimli::{constants, AttributeValue::Encoding, DebuggingInformationEntry, Reader, Unit}; @@ -27,7 +24,7 @@ pub(crate) fn handle_base_type>( unit: &Unit, entry: &DebuggingInformationEntry, debug_info_builder_context: &DebugInfoBuilderContext, -) -> Option> { +) -> Option { // All base types have: // DW_AT_encoding (our concept of type_class) // DW_AT_byte_size and/or DW_AT_bit_size @@ -73,7 +70,7 @@ pub(crate) fn handle_enum>( unit: &Unit, entry: &DebuggingInformationEntry, debug_info_builder_context: &DebugInfoBuilderContext, -) -> Option> { +) -> Option { // All base types have: // DW_AT_byte_size // *DW_AT_name @@ -132,7 +129,7 @@ pub(crate) fn handle_typedef( debug_info_builder: &mut DebugInfoBuilder, entry_type: Option, typedef_name: String, -) -> (Option>, bool) { +) -> (Option, bool) { // All base types have: // DW_AT_name // *DW_AT_type @@ -159,7 +156,7 @@ pub(crate) fn handle_pointer>( debug_info_builder: &mut DebugInfoBuilder, entry_type: Option, reference_type: ReferenceType, -) -> Option> { +) -> Option { // All pointer types have: // DW_AT_type // *DW_AT_byte_size @@ -174,7 +171,7 @@ pub(crate) fn handle_pointer>( if let Some(entry_type_offset) = entry_type { let parent_type = debug_info_builder.get_type(entry_type_offset).unwrap().1; Some(Type::pointer_of_width( - parent_type.as_ref(), + &parent_type, pointer_size, false, false, @@ -182,7 +179,7 @@ pub(crate) fn handle_pointer>( )) } else { Some(Type::pointer_of_width( - Type::void().as_ref(), + &Type::void(), pointer_size, false, false, @@ -192,7 +189,7 @@ pub(crate) fn handle_pointer>( } else if let Some(entry_type_offset) = entry_type { let parent_type = debug_info_builder.get_type(entry_type_offset).unwrap().1; Some(Type::pointer_of_width( - parent_type.as_ref(), + &parent_type, debug_info_builder_context.default_address_size(), false, false, @@ -200,7 +197,7 @@ pub(crate) fn handle_pointer>( )) } else { Some(Type::pointer_of_width( - Type::void().as_ref(), + &Type::void(), debug_info_builder_context.default_address_size(), false, false, @@ -214,7 +211,7 @@ pub(crate) fn handle_array>( entry: &DebuggingInformationEntry, debug_info_builder: &mut DebugInfoBuilder, entry_type: Option, -) -> Option> { +) -> Option { // All array types have: // DW_AT_type // *DW_AT_name @@ -234,22 +231,16 @@ pub(crate) fn handle_array>( let mut children = tree.root().unwrap().children(); // TODO : This is currently applying the size in reverse order - let mut result_type: Option> = None; + let mut result_type: Option = None; while let Ok(Some(child)) = children.next() { if let Some(inner_type) = result_type { - result_type = Some(Type::array( - inner_type.as_ref(), - get_subrange_size(child.entry()), - )); + result_type = Some(Type::array(&inner_type, get_subrange_size(child.entry()))); } else { - result_type = Some(Type::array( - parent_type.as_ref(), - get_subrange_size(child.entry()), - )); + result_type = Some(Type::array(&parent_type, get_subrange_size(child.entry()))); } } - result_type.map_or(Some(Type::array(parent_type.as_ref(), 0)), Some) + result_type.map_or(Some(Type::array(&parent_type, 0)), Some) } else { None } @@ -261,7 +252,7 @@ pub(crate) fn handle_function>( debug_info_builder_context: &DebugInfoBuilderContext, debug_info_builder: &mut DebugInfoBuilder, entry_type: Option, -) -> Option> { +) -> Option { // All subroutine types have: // *DW_AT_name // *DW_AT_type (if not provided, void) @@ -301,7 +292,7 @@ pub(crate) fn handle_function>( name.clone(), Type::named_type_from_type( name, - &Type::function::<&binaryninja::types::Type>(return_type.as_ref(), &[], false), + &Type::function::<&binaryninja::types::Type>(&return_type, &[], false), ), false, ); @@ -339,7 +330,7 @@ pub(crate) fn handle_function>( } Some(Type::function( - return_type.as_ref(), + &return_type, ¶meters, variable_arguments, )) @@ -348,7 +339,7 @@ pub(crate) fn handle_function>( pub(crate) fn handle_const( debug_info_builder: &mut DebugInfoBuilder, entry_type: Option, -) -> Option> { +) -> Option { // All const types have: // ?DW_AT_allocated // ?DW_AT_associated @@ -359,7 +350,7 @@ pub(crate) fn handle_const( if let Some(entry_type_offset) = entry_type { let parent_type = debug_info_builder.get_type(entry_type_offset).unwrap().1; - Some((*parent_type).to_builder().set_const(true).finalize()) + Some(parent_type.to_builder().set_const(true).finalize()) } else { Some(TypeBuilder::void().set_const(true).finalize()) } @@ -368,7 +359,7 @@ pub(crate) fn handle_const( pub(crate) fn handle_volatile( debug_info_builder: &mut DebugInfoBuilder, entry_type: Option, -) -> Option> { +) -> Option { // All const types have: // ?DW_AT_allocated // ?DW_AT_associated @@ -379,7 +370,7 @@ pub(crate) fn handle_volatile( if let Some(entry_type_offset) = entry_type { let parent_type = debug_info_builder.get_type(entry_type_offset).unwrap().1; - Some((*parent_type).to_builder().set_volatile(true).finalize()) + Some(parent_type.to_builder().set_volatile(true).finalize()) } else { Some(TypeBuilder::void().set_volatile(true).finalize()) } diff --git a/rust/examples/dwarf/dwarf_import/src/dwarfdebuginfo.rs b/rust/examples/dwarf/dwarf_import/src/dwarfdebuginfo.rs index 4db125c43..46668032f 100644 --- a/rust/examples/dwarf/dwarf_import/src/dwarfdebuginfo.rs +++ b/rust/examples/dwarf/dwarf_import/src/dwarfdebuginfo.rs @@ -95,7 +95,7 @@ impl FunctionInfoBuilder { // TODO : Don't make this pub...fix the value thing pub(crate) struct DebugType { name: String, - t: Ref, + t: Type, commit: bool, } @@ -226,7 +226,7 @@ impl DebugInfoBuilder { self.types.values() } - pub(crate) fn add_type(&mut self, type_uid: TypeUID, name: String, t: Ref, commit: bool) { + pub(crate) fn add_type(&mut self, type_uid: TypeUID, name: String, t: Type, commit: bool) { if let Some(DebugType { name: existing_name, t: existing_type, @@ -255,7 +255,7 @@ impl DebugInfoBuilder { } // TODO : Non-copy? - pub(crate) fn get_type(&self, type_uid: TypeUID) -> Option<(String, Ref)> { + pub(crate) fn get_type(&self, type_uid: TypeUID) -> Option<(String, Type)> { self.types .get(&type_uid) .map(|type_ref_ref| (type_ref_ref.name.clone(), type_ref_ref.t.clone())) @@ -290,7 +290,7 @@ impl DebugInfoBuilder { fn commit_types(&self, debug_info: &mut DebugInfo) { for debug_type in self.types() { if debug_type.commit { - debug_info.add_type(debug_type.name.clone(), debug_type.t.as_ref(), &[]); + debug_info.add_type(debug_type.name.clone(), &debug_type.t, &[]); // TODO : Components } } @@ -308,7 +308,7 @@ impl DebugInfoBuilder { } } - fn get_function_type(&self, function: &FunctionInfoBuilder) -> Ref { + fn get_function_type(&self, function: &FunctionInfoBuilder) -> Type { let return_type = match function.return_type { Some(return_type_id) => Conf::new(self.get_type(return_type_id).unwrap().1.clone(), 0), _ => Conf::new(binaryninja::types::Type::void(), 0), diff --git a/rust/examples/dwarf/dwarf_import/src/types.rs b/rust/examples/dwarf/dwarf_import/src/types.rs index 38bd36ea5..dd64ac0bc 100644 --- a/rust/examples/dwarf/dwarf_import/src/types.rs +++ b/rust/examples/dwarf/dwarf_import/src/types.rs @@ -16,11 +16,8 @@ use crate::die_handlers::*; use crate::dwarfdebuginfo::{DebugInfoBuilder, DebugInfoBuilderContext, TypeUID}; use crate::helpers::*; -use binaryninja::{ - rc::*, - types::{ - MemberAccess, MemberScope, ReferenceType, StructureBuilder, StructureType, Type, TypeClass, - }, +use binaryninja::types::{ + MemberAccess, MemberScope, ReferenceType, StructureBuilder, StructureType, Type, TypeClass, }; use gimli::{constants, DebuggingInformationEntry, Reader, Unit}; @@ -164,7 +161,7 @@ fn do_structure_parse>( }); structure_builder.insert( - child_type.as_ref(), + &child_type, child_name, struct_offset, false, @@ -173,7 +170,7 @@ fn do_structure_parse>( ); } else { structure_builder.append( - child_type.as_ref(), + &child_type, child_name, MemberAccess::NoAccess, MemberScope::NoScope, @@ -270,7 +267,7 @@ pub(crate) fn get_type>( // Collect the required information to create a type and add it to the type map. Also, add the dependencies of this type to the type's typeinfo // Create the type, make a TypeInfo for it, and add it to the debug info - let (type_def, mut commit): (Option>, bool) = match entry.tag() { + let (type_def, mut commit): (Option, bool) = match entry.tag() { constants::DW_TAG_base_type => ( handle_base_type(unit, entry, debug_info_builder_context), false, diff --git a/rust/examples/pdb-ng/src/parser.rs b/rust/examples/pdb-ng/src/parser.rs index cbc4f07a3..3c5a6c886 100644 --- a/rust/examples/pdb-ng/src/parser.rs +++ b/rust/examples/pdb-ng/src/parser.rs @@ -65,7 +65,7 @@ pub struct PDBParserInstance<'a, S: Source<'a> + 'a> { /// TypeIndex -> ParsedType enum used during parsing pub(crate) indexed_types: HashMap, /// QName -> Binja Type for finished types - pub(crate) named_types: HashMap>, + pub(crate) named_types: HashMap, /// Raw (mangled) name -> TypeIndex for resolving forward references pub(crate) full_type_indices: HashMap, /// Stack of types we're currently parsing @@ -163,7 +163,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { ) -> Result<()> { self.parse_types(Self::split_progress(&progress, 0, &[1.0, 3.0, 0.5, 0.5]))?; for (name, ty) in self.named_types.iter() { - self.debug_info.add_type(name, ty.as_ref(), &[]); // TODO : Components + self.debug_info.add_type(name, &ty, &[]); // TODO : Components } info!("PDB found {} types", self.named_types.len()); @@ -219,7 +219,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { ) }); self.debug_info - .add_data_variable_info(DataVariableAndName::new( + .add_data_variable_info(&DataVariableAndName::new( address, real_type, true, @@ -312,40 +312,40 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { TypeClass::StructureTypeClass => { if let Ok(structure) = ty.get_structure() { if let Ok(members) = structure.members() { - for member in members { - self.collect_names(member.ty.contents.as_ref(), unknown_names); + for member in &members { + self.collect_names(&member.ty().contents, unknown_names); } } if let Ok(bases) = structure.base_structures() { - for base in bases { - self.collect_name(base.ty.as_ref(), unknown_names); + for base in &bases { + self.collect_name(&base.ty, unknown_names); } } } } TypeClass::PointerTypeClass => { if let Ok(target) = ty.target() { - self.collect_names(target.contents.as_ref(), unknown_names); + self.collect_names(&target.contents, unknown_names); } } TypeClass::ArrayTypeClass => { if let Ok(element_type) = ty.element_type() { - self.collect_names(element_type.contents.as_ref(), unknown_names); + self.collect_names(&element_type.contents, unknown_names); } } TypeClass::FunctionTypeClass => { if let Ok(return_value) = ty.return_value() { - self.collect_names(return_value.contents.as_ref(), unknown_names); + self.collect_names(&return_value.contents, unknown_names); } if let Ok(params) = ty.parameters() { - for param in params { - self.collect_names(param.t.contents.as_ref(), unknown_names); + for param in ¶ms { + self.collect_names(¶m.t, unknown_names); } } } TypeClass::NamedTypeReferenceClass => { if let Ok(ntr) = ty.get_named_type_reference() { - self.collect_name(ntr.as_ref(), unknown_names); + self.collect_name(&ntr, unknown_names); } } _ => {} @@ -375,17 +375,17 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { ParsedSymbol::Data(ParsedDataSymbol { type_: Some(type_), .. }) => { - self.collect_names(type_.contents.as_ref(), &mut unknown_names); + self.collect_names(&type_.contents, &mut unknown_names); } ParsedSymbol::Procedure(ParsedProcedure { type_: Some(type_), locals, .. }) => { - self.collect_names(type_.contents.as_ref(), &mut unknown_names); + self.collect_names(&type_.contents, &mut unknown_names); for l in locals { if let Some(ltype) = &l.type_ { - self.collect_names(ltype.contents.as_ref(), &mut unknown_names); + self.collect_names(<ype.contents, &mut unknown_names); } } } @@ -403,7 +403,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { match class { NamedTypeReferenceClass::UnknownNamedTypeClass | NamedTypeReferenceClass::TypedefNamedTypeClass => { - self.debug_info.add_type(name, Type::void().as_ref(), &[]); // TODO : Components + self.debug_info.add_type(name, &Type::void(), &[]); // TODO : Components } NamedTypeReferenceClass::ClassNamedTypeClass | NamedTypeReferenceClass::StructNamedTypeClass @@ -426,7 +426,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { self.debug_info.add_type( name, - Type::structure(structure.finalize().as_ref()).as_ref(), + &Type::structure(&structure.finalize()), &[], // TODO : Components ); } @@ -434,12 +434,11 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { let enumeration = EnumerationBuilder::new(); self.debug_info.add_type( name, - Type::enumeration( - enumeration.finalize().as_ref(), + &Type::enumeration( + &enumeration.finalize(), self.arch.default_integer_size(), false, - ) - .as_ref(), + ), &[], // TODO : Components ); } diff --git a/rust/examples/pdb-ng/src/struct_grouper.rs b/rust/examples/pdb-ng/src/struct_grouper.rs index 042eb979c..1cf1925a1 100644 --- a/rust/examples/pdb-ng/src/struct_grouper.rs +++ b/rust/examples/pdb-ng/src/struct_grouper.rs @@ -414,7 +414,7 @@ fn apply_groups( let mut inner = StructureBuilder::new(); apply_groups(members, &mut inner, children, inner_offset); structure.insert( - &Conf::new(Type::structure(inner.finalize().as_ref()), max_confidence()), + &Conf::new(Type::structure(&inner.finalize()), max_confidence()), format!("__inner{}", i), inner_offset - offset, false, @@ -427,7 +427,7 @@ fn apply_groups( inner.set_structure_type(StructureType::UnionStructureType); apply_groups(members, &mut inner, children, inner_offset); structure.insert( - &Conf::new(Type::structure(inner.finalize().as_ref()), max_confidence()), + &Conf::new(Type::structure(&inner.finalize()), max_confidence()), format!("__inner{}", i), inner_offset - offset, false, diff --git a/rust/examples/pdb-ng/src/symbol_parser.rs b/rust/examples/pdb-ng/src/symbol_parser.rs index 7f418747f..b1e1d0aa4 100644 --- a/rust/examples/pdb-ng/src/symbol_parser.rs +++ b/rust/examples/pdb-ng/src/symbol_parser.rs @@ -36,7 +36,6 @@ use binaryninja::architecture::{Architecture, ArchitectureExt, Register}; use binaryninja::binaryninjacore_sys::BNVariableSourceType; use binaryninja::binaryview::BinaryViewBase; use binaryninja::demangle::demangle_ms; -use binaryninja::rc::Ref; use binaryninja::types::{ max_confidence, min_confidence, Conf, ConfMergable, FunctionParameter, QualifiedName, StructureBuilder, Type, TypeClass, Variable, @@ -64,7 +63,7 @@ pub struct ParsedDataSymbol { /// Symbol name pub name: SymbolNames, /// Type if known - pub type_: Option>>, + pub type_: Option>, } /// Parsed functions and function-y symbols @@ -77,7 +76,7 @@ pub struct ParsedProcedure { /// Symbol name pub name: SymbolNames, /// Function type if known - pub type_: Option>>, + pub type_: Option>, /// List of local variables (TODO: use these) pub locals: Vec, } @@ -97,7 +96,7 @@ pub struct ParsedVariable { /// Variable name pub name: String, /// Variable type if known - pub type_: Option>>, + pub type_: Option>, /// Location(s) where the variable is stored. PDB lets you store a variable in multiple locations /// despite binja not really understanding that. Length is probably never zero pub storage: Vec, @@ -866,8 +865,8 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { &self, index: SymbolIndex, type_index: TypeIndex, - demangled_type: Option>>, - ) -> Result<(Option>>, Vec)> { + demangled_type: Option>, + ) -> Result<(Option>, Vec)> { // So generally speaking, here's the information we have: // - The function type is usually accurate wrt the parameter locations // - The parameter symbols have the names we want for the params @@ -921,10 +920,13 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { .contents .parameters() .map_err(|_| anyhow!("no params"))?; - let mut fancy_params = fancy_type + let mut fancy_params: Vec<_> = fancy_type .contents .parameters() - .map_err(|_| anyhow!("no params"))?; + .map_err(|_| anyhow!("no params"))? + .iter() + .cloned() + .collect(); // Collect all the parameters we are expecting from the symbols let mut parsed_params = vec![]; @@ -958,15 +960,17 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { } } - self.log(|| format!("Raw params: {:#x?}", raw_params)); - self.log(|| format!("Fancy params: {:#x?}", fancy_params)); + self.log(|| { + format!( + "Raw params: {:#x?}", + raw_params.iter().collect::>() + ) + }); + self.log(|| format!("Fancy params: {:#x?}", &fancy_params)); self.log(|| format!("Parsed params: {:#x?}", parsed_params)); // We expect one parameter for each unnamed parameter in the marked up type - let expected_param_count = fancy_params - .iter() - .filter(|p| p.name.as_str().is_empty()) - .count(); + let expected_param_count = fancy_params.iter().filter(|p| p.name().is_empty()).count(); // Sanity if expected_param_count != raw_params.len() { return Err(anyhow!( @@ -994,8 +998,8 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { let mut i = 0; for p in fancy_params.iter_mut() { - if p.name.as_str().is_empty() { - if p.t.contents != expected_parsed_params[i].t.contents { + if p.name().is_empty() { + if p.t != expected_parsed_params[i].t { self.log(|| { format!( "Suspicious parameter {}: {:?} vs {:?}", @@ -1003,10 +1007,10 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { ) }); } - if expected_parsed_params[i].name.as_str() == "__formal" { - p.name = format!("__formal{}", i); + if expected_parsed_params[i].name() == "__formal" { + p.set_name(format!("__formal{}", i)); } else { - p.name = expected_parsed_params[i].name.clone(); + p.set_name(&expected_parsed_params[i].name()); } i += 1; } @@ -1029,10 +1033,10 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { let locations = cc.contents.variables_for_parameters(&fancy_params, None); for (p, new_location) in fancy_params.iter_mut().zip(locations.into_iter()) { - p.location = Some(new_location); + p.set_location(Some(new_location)); } - self.log(|| format!("Final params: {:#x?}", fancy_params)); + self.log(|| format!("Final params: {:#x?}", &fancy_params)); // Use the new locals we've parsed to make the Real Definitely True function type let fancy_type = Conf::new( @@ -1041,7 +1045,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { .contents .return_value() .map_err(|_| anyhow!("no ret"))?, - fancy_params.as_slice(), + &fancy_params, fancy_type.contents.has_variable_arguments().contents, &cc, fancy_type.contents.stack_adjustment(), @@ -1191,7 +1195,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { let mut target_name = None; let mut thunk_name = None; - let mut fn_type: Option>> = None; + let mut fn_type: Option> = None; // These have the same name as their target, so look that up if let Some(syms) = self.addressed_symbols.get(&target_address) { @@ -1749,7 +1753,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { &self, raw_name: &String, rva: Rva, - ) -> Result<(Option>>, Option)> { + ) -> Result<(Option>, Option)> { let (mut t, mut name) = match demangle_ms(&self.arch, raw_name.clone(), true) { Ok((Some(t), name)) => (Some(Conf::new(t, DEMANGLE_CONFIDENCE)), name), Ok((_, name)) => (None, name), @@ -1763,8 +1767,9 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { .contents .parameters() .map_err(|_| anyhow!("no parameters"))?; - if let [p] = parameters.as_slice() { - if p.t.contents.type_class() == TypeClass::VoidTypeClass { + if parameters.len() == 1 { + let p = parameters.get(0); + if p.t.type_class() == TypeClass::VoidTypeClass { t = Some(Conf::new( Type::function::<_>( &ty.contents @@ -1829,7 +1834,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { if let Some(ty) = self.named_types.get(search_type) { // Fallback in case we don't find a specific one t = Some(Conf::new( - Type::named_type_from_type(search_type, ty.as_ref()), + Type::named_type_from_type(search_type, &ty), max_confidence(), )); @@ -1848,7 +1853,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { if let Some(ty) = self.named_types.get(&lengthy_name) { // Wow! t = Some(Conf::new( - Type::named_type_from_type(lengthy_name, ty.as_ref()), + Type::named_type_from_type(lengthy_name, &ty), max_confidence(), )); } else { @@ -1883,7 +1888,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { if let Some(ty) = self.named_types.get(&vt_name) { t = Some(Conf::new( - Type::named_type_from_type(&vt_name, ty.as_ref()), + Type::named_type_from_type(&vt_name, &ty), max_confidence(), )); } else { @@ -1895,15 +1900,14 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { if let Some(ty) = self.named_types.get(&vt_name) { t = Some(Conf::new( - Type::named_type_from_type(&vt_name, ty.as_ref()), + Type::named_type_from_type(&vt_name, &ty), max_confidence(), )); } else { t = Some(Conf::new( Type::named_type_from_type( &vt_name, - Type::structure(StructureBuilder::new().finalize().as_ref()) - .as_ref(), + &Type::structure(&StructureBuilder::new().finalize()), ), DEMANGLE_CONFIDENCE, )); @@ -1935,31 +1939,34 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { fn make_lengthy_type( &self, - base_type: &Ref, + base_type: &Type, base_address: u64, - ) -> Result, usize)>> { + ) -> Result> { if base_type.type_class() != TypeClass::StructureTypeClass { return Ok(None); } let structure = base_type .get_structure() .map_err(|_| anyhow!("Expected structure"))?; - let mut members = structure + let mut members: Vec<_> = structure .members() - .map_err(|_| anyhow!("Expected structure to have members"))?; + .map_err(|_| anyhow!("Expected structure to have members"))? + .iter() + .cloned() + .collect(); let last_member = members .last_mut() .ok_or_else(|| anyhow!("Not enough members"))?; - if last_member.ty.contents.type_class() != TypeClass::ArrayTypeClass { + if last_member.ty().contents.type_class() != TypeClass::ArrayTypeClass { return Ok(None); } - if last_member.ty.contents.count() != 0 { + if last_member.ty().contents.count() != 0 { return Ok(None); } let member_element = last_member - .ty + .ty() .contents .element_type() .map_err(|_| anyhow!("Last member has no type"))? @@ -1985,10 +1992,13 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { } // Make a new copy of the type with the correct element count - last_member.ty.contents = Type::array(member_element.as_ref(), element_count); + last_member.set_type(Conf::new( + Type::array(&member_element, element_count), + last_member.ty().confidence, + )); Ok(Some(( - Type::structure(StructureBuilder::from(members).finalize().as_ref()), + Type::structure(&StructureBuilder::from(members.iter()).finalize()), element_count as usize, ))) } diff --git a/rust/examples/pdb-ng/src/type_parser.rs b/rust/examples/pdb-ng/src/type_parser.rs index dc23f2ff1..fb1871d96 100644 --- a/rust/examples/pdb-ng/src/type_parser.rs +++ b/rust/examples/pdb-ng/src/type_parser.rs @@ -55,9 +55,9 @@ static BUILTIN_NAMES: &[&'static str] = &[ #[derive(Debug, Clone)] pub struct ParsedProcedureType { /// Interpreted type of the method, with thisptr, __return, etc - pub method_type: Ref, + pub method_type: Type, /// Base method type right outta the pdb with no frills - pub raw_method_type: Ref, + pub raw_method_type: Type, } /// Bitfield member type, if we ever get around to implementing these @@ -68,14 +68,14 @@ pub struct ParsedBitfieldType { /// Bit offset in the current bitfield set pub position: u64, /// Underlying type of the whole bitfield set - pub ty: Ref, + pub ty: Type, } /// Parsed member of a class/structure, basically just binaryninja::StructureMember but with bitfields :( #[derive(Debug, Clone)] pub struct ParsedMember { /// Member type - pub ty: Conf>, + pub ty: Conf, /// Member name pub name: String, /// Offset in structure @@ -122,11 +122,11 @@ pub struct ParsedMemberFunction { /// Parent class's name pub class_name: String, /// Interpreted type of the method, with thisptr, __return, etc - pub method_type: Ref, + pub method_type: Type, /// Base method type right outta the pdb with no frills - pub raw_method_type: Ref, + pub raw_method_type: Type, /// Type of thisptr object, if relevant - pub this_pointer_type: Option>, + pub this_pointer_type: Option, /// Adjust to thisptr at start, for virtual bases or something pub this_adjustment: usize, } @@ -137,11 +137,11 @@ pub struct VirtualBaseClass { /// Base class name pub base_name: String, /// Base class type - pub base_type: Ref, + pub base_type: Type, /// Offset in this class where the base's fields are located pub base_offset: u64, /// Type of vbtable, probably - pub base_table_type: Ref, + pub base_table_type: Type, /// Offset of this base in the vbtable pub base_table_offset: u64, } @@ -150,9 +150,9 @@ pub struct VirtualBaseClass { #[derive(Debug, Clone)] pub enum ParsedType { /// No info other than type data - Bare(Ref), + Bare(Type), /// Named fully parsed class/enum/union/etc type - Named(String, Ref), + Named(String, Type), /// Function procedure Procedure(ParsedProcedureType), /// Bitfield entries @@ -372,25 +372,23 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { let bare_type = match type_class { NamedTypeReferenceClass::ClassNamedTypeClass => Type::structure( - StructureBuilder::new() + &StructureBuilder::new() .set_structure_type(StructureType::ClassStructureType) - .finalize() - .as_ref(), + .finalize(), ), // Missing typedefs are just going to become structures NamedTypeReferenceClass::UnknownNamedTypeClass | NamedTypeReferenceClass::TypedefNamedTypeClass | NamedTypeReferenceClass::StructNamedTypeClass => { - Type::structure(StructureBuilder::new().finalize().as_ref()) + Type::structure(&StructureBuilder::new().finalize()) } NamedTypeReferenceClass::UnionNamedTypeClass => Type::structure( - StructureBuilder::new() + &StructureBuilder::new() .set_structure_type(StructureType::UnionStructureType) - .finalize() - .as_ref(), + .finalize(), ), NamedTypeReferenceClass::EnumNamedTypeClass => Type::enumeration( - EnumerationBuilder::new().finalize().as_ref(), + &EnumerationBuilder::new().finalize(), self.arch.default_integer_size(), false, ), @@ -428,11 +426,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { } /// Lookup a type in the parsed types by its index (ie for a procedure) - pub(crate) fn lookup_type( - &self, - index: &TypeIndex, - fancy_procs: bool, - ) -> Result>> { + pub(crate) fn lookup_type(&self, index: &TypeIndex, fancy_procs: bool) -> Result> { match self.indexed_types.get(index) { Some(ParsedType::Bare(ty)) => Ok(Some(ty.clone())), Some(ParsedType::Named(name, ty)) => Ok(Some(Type::named_type_from_type(name, &ty))), @@ -467,7 +461,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { &self, index: &TypeIndex, fancy_procs: bool, - ) -> Result>>> { + ) -> Result>> { match self.lookup_type(index, fancy_procs)? { Some(ty) if ty.type_class() == TypeClass::VoidTypeClass => Ok(Some(Conf::new(ty, 0))), Some(ty) => { @@ -663,42 +657,34 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { PrimitiveKind::Bool32 => Ok(Type::int(4, false)), PrimitiveKind::Bool64 => Ok(Type::int(8, false)), // Hack: this isn't always defined - PrimitiveKind::HRESULT => Ok(Type::named_type_from_type( - "HRESULT", - Type::int(4, true).as_ref(), - )), + PrimitiveKind::HRESULT => { + Ok(Type::named_type_from_type("HRESULT", &Type::int(4, true))) + } _ => Err(anyhow!("Unknown type unimplmented")), }?; // TODO: Pointer suffix is not exposed match data.indirection { Some(Indirection::Near16) => Ok(Some(Box::new(ParsedType::Bare(Type::pointer( - &self.arch, - base.as_ref(), + &self.arch, &base, ))))), Some(Indirection::Far16) => Ok(Some(Box::new(ParsedType::Bare(Type::pointer( - &self.arch, - base.as_ref(), + &self.arch, &base, ))))), Some(Indirection::Huge16) => Ok(Some(Box::new(ParsedType::Bare(Type::pointer( - &self.arch, - base.as_ref(), + &self.arch, &base, ))))), Some(Indirection::Near32) => Ok(Some(Box::new(ParsedType::Bare(Type::pointer( - &self.arch, - base.as_ref(), + &self.arch, &base, ))))), Some(Indirection::Far32) => Ok(Some(Box::new(ParsedType::Bare(Type::pointer( - &self.arch, - base.as_ref(), + &self.arch, &base, ))))), Some(Indirection::Near64) => Ok(Some(Box::new(ParsedType::Bare(Type::pointer( - &self.arch, - base.as_ref(), + &self.arch, &base, ))))), Some(Indirection::Near128) => Ok(Some(Box::new(ParsedType::Bare(Type::pointer( - &self.arch, - base.as_ref(), + &self.arch, &base, ))))), None => Ok(Some(Box::new(ParsedType::Bare(base)))), } @@ -730,7 +716,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { ClassKind::Interface => NamedTypeReferenceClass::StructNamedTypeClass, }; return Ok(Some(Box::new(ParsedType::Bare(Type::named_type( - &*NamedTypeReference::new(ntr_class, QualifiedName::from(class_name)), + &NamedTypeReference::new(ntr_class, &QualifiedName::from(class_name)), ))))); } @@ -752,7 +738,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { let _ = success?; } - let new_type = Type::structure(structure.finalize().as_ref()); + let new_type = Type::structure(&structure.finalize()); Ok(Some(Box::new(ParsedType::Named(class_name, new_type)))) } @@ -840,13 +826,10 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { if let Some(builder) = bitfield_builder.take() { combined_bitfield_members.push(ParsedMember { ty: Conf::new( - Type::structure(builder.finalize().as_ref()), + Type::structure(&builder.finalize()), max_confidence(), ), - name: bitfield_name( - last_bitfield_offset, - last_bitfield_idx, - ), + name: bitfield_name(last_bitfield_offset, last_bitfield_idx), offset: last_bitfield_offset, access: MemberAccess::PublicAccess, scope: MemberScope::NoScope, @@ -876,14 +859,8 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { (None, None) => { if let Some(builder) = bitfield_builder.take() { combined_bitfield_members.push(ParsedMember { - ty: Conf::new( - Type::structure(builder.finalize().as_ref()), - max_confidence(), - ), - name: bitfield_name( - last_bitfield_offset, - last_bitfield_idx, - ), + ty: Conf::new(Type::structure(&builder.finalize()), max_confidence()), + name: bitfield_name(last_bitfield_offset, last_bitfield_idx), offset: last_bitfield_offset, access: MemberAccess::PublicAccess, scope: MemberScope::NoScope, @@ -900,10 +877,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { } if let Some(builder) = bitfield_builder.take() { combined_bitfield_members.push(ParsedMember { - ty: Conf::new( - Type::structure(builder.finalize().as_ref()), - max_confidence(), - ), + ty: Conf::new(Type::structure(&builder.finalize()), max_confidence()), name: bitfield_name(last_bitfield_offset, last_bitfield_idx), offset: last_bitfield_offset, access: MemberAccess::PublicAccess, @@ -950,9 +924,9 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { _ => NamedTypeReferenceClass::StructNamedTypeClass, }; bases.push(BaseStructure::new( - NamedTypeReference::new(ntr_class, name.into()), + NamedTypeReference::new(ntr_class, &name.into()), base.offset, - base.ty.contents.width(), + base.ty().contents.width(), )); } ParsedType::VBaseClass(VirtualBaseClass { @@ -982,7 +956,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { _ => NamedTypeReferenceClass::StructNamedTypeClass, }; bases.push(BaseStructure::new( - NamedTypeReference::new(ntr_class, base_name.into()), + NamedTypeReference::new(ntr_class, &base_name.into()), *base_offset, base_type.width(), )); @@ -1052,7 +1026,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { NamedTypeReferenceClass::StructNamedTypeClass }; vt_bases.push(BaseStructure::new( - NamedTypeReference::new(ntr_class, vt_base_name.into()), + NamedTypeReference::new(ntr_class, &vt_base_name.into()), 0, vt_base_type.width(), )); @@ -1095,7 +1069,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { vt.set_width(min_width); - let vt_type = Type::structure(vt.finalize().as_ref()); + let vt_type = Type::structure(&vt.finalize()); // Need to insert a new named type for the vtable let mut vt_name = self .namespace_stack @@ -1108,7 +1082,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { let vt_pointer = Type::pointer( &self.arch, &Conf::new( - Type::named_type_from_type(&QualifiedName::from(vt_name), vt_type.as_ref()), + Type::named_type_from_type(&QualifiedName::from(vt_name), &vt_type), max_confidence(), ), ); @@ -1208,7 +1182,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { // It looks like pdb stores varargs by having the final argument be void let mut is_varargs = false; if let Some(last) = arguments.pop() { - if last.t.contents.as_ref().type_class() == TypeClass::VoidTypeClass { + if last.t.type_class() == TypeClass::VoidTypeClass { is_varargs = true; } else { arguments.push(last); @@ -1370,7 +1344,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { // Try to resolve the full base type let resolved_type = match self.try_type_index_to_bare(data.base_class, finder, true)? { - Some(ty) => Type::named_type_from_type(&member_name, ty.as_ref()), + Some(ty) => Type::named_type_from_type(&member_name, &ty), None => t.clone(), }; @@ -1490,7 +1464,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { // It looks like pdb stores varargs by having the final argument be void let mut is_varargs = false; if let Some(last) = arguments.pop() { - if last.t.contents.as_ref().type_class() == TypeClass::VoidTypeClass { + if last.t.type_class() == TypeClass::VoidTypeClass { is_varargs = true; } else { arguments.push(last); @@ -1562,8 +1536,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { if let Some(base) = base { Ok(Some(Box::new(ParsedType::Bare(Type::pointer( - &self.arch, - base.as_ref(), + &self.arch, &base, ))))) } else { Ok(None) @@ -1579,7 +1552,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { let base = self.try_type_index_to_bare(data.underlying_type, finder, false)?; if let Some(base) = base { - let builder = TypeBuilder::new(base.as_ref()); + let builder = TypeBuilder::new(&base); builder.set_const(data.constant); builder.set_volatile(data.volatile); Ok(Some(Box::new(ParsedType::Bare(builder.finalize())))) @@ -1609,7 +1582,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { let ntr_class = NamedTypeReferenceClass::EnumNamedTypeClass; return Ok(Some(Box::new(ParsedType::Bare(Type::named_type( - &*NamedTypeReference::new(ntr_class, QualifiedName::from(enum_name)), + &NamedTypeReference::new(ntr_class, &QualifiedName::from(enum_name)), ))))); } @@ -1637,7 +1610,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { }; let new_type = Type::enumeration( - enumeration.finalize().as_ref(), + &enumeration.finalize(), underlying.width() as usize, underlying.is_signed().contents, ); @@ -1651,20 +1624,22 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { _finder: &mut ItemFinder, ) -> Result>> { self.log(|| format!("Got Enumerate type: {:x?}", data)); - Ok(Some(Box::new(ParsedType::Enumerate(EnumerationMember { - name: data.name.to_string().to_string(), - value: match data.value { - Variant::U8(v) => v as u64, - Variant::U16(v) => v as u64, - Variant::U32(v) => v as u64, - Variant::U64(v) => v as u64, - Variant::I8(v) => (v as i64) as u64, - Variant::I16(v) => (v as i64) as u64, - Variant::I32(v) => (v as i64) as u64, - Variant::I64(v) => (v as i64) as u64, - }, - is_default: false, - })))) + Ok(Some(Box::new(ParsedType::Enumerate( + EnumerationMember::new( + &data.name.to_string(), + match data.value { + Variant::U8(v) => v as u64, + Variant::U16(v) => v as u64, + Variant::U32(v) => v as u64, + Variant::U64(v) => v as u64, + Variant::I8(v) => (v as i64) as u64, + Variant::I16(v) => (v as i64) as u64, + Variant::I32(v) => (v as i64) as u64, + Variant::I64(v) => (v as i64) as u64, + }, + false, + ), + )))) } fn handle_array_type( @@ -1706,7 +1681,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { counts[j] /= new_type.width(); } - new_type = Type::array(new_type.as_ref(), counts[i] as u64); + new_type = Type::array(&new_type, counts[i] as u64); } Ok(Some(Box::new(ParsedType::Bare(new_type)))) @@ -1736,7 +1711,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { let ntr_class = NamedTypeReferenceClass::UnionNamedTypeClass; return Ok(Some(Box::new(ParsedType::Bare(Type::named_type( - &*NamedTypeReference::new(ntr_class, QualifiedName::from(union_name)), + &NamedTypeReference::new(ntr_class, &QualifiedName::from(union_name)), ))))); } @@ -1749,7 +1724,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { self.namespace_stack.pop(); let _ = success?; - let new_type = Type::structure(structure.finalize().as_ref()); + let new_type = Type::structure(&structure.finalize()); Ok(Some(Box::new(ParsedType::Named(union_name, new_type)))) } @@ -1809,10 +1784,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { ); } structure.insert( - &Conf::new( - Type::structure(inner_struct.finalize().as_ref()), - max_confidence(), - ), + &Conf::new(Type::structure(&inner_struct.finalize()), max_confidence()), format!("__inner{:x}", i), 0, false, @@ -1897,10 +1869,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { )); } else { args.push(FunctionParameter::new( - Conf::new( - Type::pointer(self.arch.as_ref(), ty.as_ref()), - max_confidence(), - ), + Conf::new(Type::pointer(self.arch.as_ref(), &ty), max_confidence()), "".to_string(), None, )); @@ -1945,7 +1914,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { index: TypeIndex, finder: &mut ItemFinder, fully_resolve: bool, - ) -> Result> { + ) -> Result { match self.try_type_index_to_bare(index, finder, fully_resolve)? { Some(ty) => Ok(ty), None => Err(anyhow!("Unresolved expected type {:?}", index)), @@ -1959,7 +1928,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { index: TypeIndex, finder: &mut ItemFinder, fully_resolve: bool, - ) -> Result>> { + ) -> Result> { let (mut type_, inner) = match self.handle_type_index(index, finder)? { Some(ParsedType::Bare(ty)) => (ty.clone(), None), Some(ParsedType::Named(name, ty)) => { @@ -1986,7 +1955,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { .name() .to_string(); if let Some(full_ntr) = self.named_types.get(&name) { - type_ = Type::named_type_from_type(&name, full_ntr.as_ref()); + type_ = Type::named_type_from_type(&name, &full_ntr); } } } @@ -2141,7 +2110,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> { fn insert_this_pointer( &self, parameters: &mut Vec, - this_type: Ref, + this_type: Type, ) -> Result<()> { parameters.insert( 0, diff --git a/rust/src/architecture.rs b/rust/src/architecture.rs index d6f11f381..6aa16c261 100644 --- a/rust/src/architecture.rs +++ b/rust/src/architecture.rs @@ -313,7 +313,7 @@ pub trait Intrinsic: Sized + Clone + Copy { fn id(&self) -> u32; /// Reeturns the list of the input names and types for this intrinsic. - fn inputs(&self) -> Array; + fn inputs(&self) -> Vec; /// Returns the list of the output types for this intrinsic. fn outputs(&self) -> Vec>; @@ -650,7 +650,7 @@ impl Intrinsic for UnusedIntrinsic { fn id(&self) -> u32 { unreachable!() } - fn inputs(&self) -> Array { + fn inputs(&self) -> Vec { unreachable!() } fn outputs(&self) -> Vec> { @@ -1007,12 +1007,20 @@ impl Intrinsic for crate::architecture::CoreIntrinsic { self.1 } - fn inputs(&self) -> Array { + fn inputs(&self) -> Vec { let mut count: usize = 0; unsafe { let inputs = BNGetArchitectureIntrinsicInputs(self.0, self.1, &mut count as *mut _); - Array::new(inputs, count, ()) + + let ret = slice::from_raw_parts_mut(inputs, count) + .iter() + .map(|x| NameAndType::ref_from_raw(x).to_owned()) + .collect(); + + BNFreeNameAndTypeList(inputs, count); + + ret } } @@ -2425,10 +2433,19 @@ where return ptr::null_mut(); }; + let inputs = intrinsic.inputs(); + let mut res: Box<[_]> = inputs.into_boxed_slice(); + unsafe { - let (inputs, inputs_len, ()) = intrinsic.inputs().into_raw(); - *count = inputs_len; - inputs + *count = res.len(); + if res.is_empty() { + ptr::null_mut() + } else { + // SAFETY NameAndType and BNNameAndType are transparent + let raw = res.as_mut_ptr() as *mut BNNameAndType; + mem::forget(res); + raw + } } } diff --git a/rust/src/binaryview.rs b/rust/src/binaryview.rs index 04d5f50da..b1452f7ae 100644 --- a/rust/src/binaryview.rs +++ b/rust/src/binaryview.rs @@ -505,7 +505,7 @@ pub trait BinaryViewExt: BinaryViewBase { ty: Option<&Type>, ) -> Result> { let raw_type = ty - .map(|t| t.as_raw() as *mut BNType) + .map(|t| unsafe { t.as_raw() as *mut BNType }) .unwrap_or(ptr::null_mut()); unsafe { diff --git a/rust/src/function.rs b/rust/src/function.rs index ec9c5a3e2..add1375f0 100644 --- a/rust/src/function.rs +++ b/rust/src/function.rs @@ -544,7 +544,7 @@ impl Function { let mut adjust_type = adjust_type.map(|adjust_type| { let adjust_type = adjust_type.into(); BNTypeWithConfidence { - type_: adjust_type.contents.as_raw(), + type_: unsafe { adjust_type.contents.as_raw() }, confidence: adjust_type.confidence, } }); @@ -813,7 +813,7 @@ impl Function { ) -> RegisterValue { let arch = arch.unwrap_or_else(|| self.arch()); let func_type = func_type - .map(|f| f.as_raw() as *mut BNType) + .map(|f| unsafe { f.as_raw() as *mut BNType }) .unwrap_or(core::ptr::null_mut()); let value = unsafe { BNGetParameterValueAtInstruction(self.handle, arch.0, addr, func_type, i) }; @@ -1104,7 +1104,7 @@ impl Function { arch: Option, ) { let arch = arch.unwrap_or_else(|| self.arch()); - let name_ptr = name.as_raw() as *const BNQualifiedName as *mut BNQualifiedName; + let name_ptr = unsafe { name.as_raw() as *const BNQualifiedName as *mut BNQualifiedName }; unsafe { BNAddUserTypeReference(self.handle, arch.0, from_addr, name_ptr) } } @@ -1129,7 +1129,7 @@ impl Function { arch: Option, ) { let arch = arch.unwrap_or_else(|| self.arch()); - let name_ptr = name.as_raw() as *const BNQualifiedName as *mut BNQualifiedName; + let name_ptr = unsafe { name.as_raw() as *const BNQualifiedName as *mut BNQualifiedName }; unsafe { BNRemoveUserTypeReference(self.handle, arch.0, from_addr, name_ptr) } } @@ -1160,7 +1160,7 @@ impl Function { ) { let size = size.unwrap_or(0); let arch = arch.unwrap_or_else(|| self.arch()); - let name_ptr = name.as_raw() as *const BNQualifiedName as *mut BNQualifiedName; + let name_ptr = unsafe { name.as_raw() as *const BNQualifiedName as *mut BNQualifiedName }; unsafe { BNAddUserTypeFieldReference(self.handle, arch.0, from_addr, name_ptr, offset, size) } @@ -1192,7 +1192,7 @@ impl Function { ) { let size = size.unwrap_or(0); let arch = arch.unwrap_or_else(|| self.arch()); - let name_ptr = name.as_raw() as *const BNQualifiedName as *mut BNQualifiedName; + let name_ptr = unsafe{ name.as_raw() as *const BNQualifiedName as *mut BNQualifiedName }; unsafe { BNRemoveUserTypeFieldReference(self.handle, arch.0, from_addr, name_ptr, offset, size) } diff --git a/rust/src/mlil/instruction.rs b/rust/src/mlil/instruction.rs index a0db9a103..19e23f8ce 100644 --- a/rust/src/mlil/instruction.rs +++ b/rust/src/mlil/instruction.rs @@ -1159,7 +1159,7 @@ impl MediumLevelILInstruction { pub fn set_expr_type<'a, T: Into>>(&self, value: T) { let type_: Conf<&'a Type> = value.into(); let mut type_raw: BNTypeWithConfidence = BNTypeWithConfidence { - type_: type_.contents.as_raw(), + type_: unsafe{ type_.contents.as_raw() }, confidence: type_.confidence, }; unsafe { BNSetMediumLevelILExprType(self.function.handle, self.index, &mut type_raw) } diff --git a/rust/src/rc.rs b/rust/src/rc.rs index f2c8da12a..dc1a502bb 100644 --- a/rust/src/rc.rs +++ b/rust/src/rc.rs @@ -233,18 +233,6 @@ impl Array

{ } } - pub(crate) unsafe fn into_raw(self) -> (*mut P::Raw, usize, P::Context) { - let contents = self.contents; - let count = self.count; - - // extract the context, because we can't move it directly, we need - // to be carefull to take the value, not droping self - let slf = mem::ManuallyDrop::new(self); - let context = mem::transmute_copy(&slf.context); - - (contents, count, context) - } - #[inline] pub fn len(&self) -> usize { self.count diff --git a/rust/src/types.rs b/rust/src/types.rs index 6790a159f..18aef7dff 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -270,7 +270,7 @@ impl From for Conf { impl From> for BNTypeWithConfidence { fn from(conf: Conf<&Type>) -> Self { Self { - type_: conf.contents.as_raw(), + type_: unsafe { conf.contents.as_raw() }, confidence: conf.confidence, } } @@ -321,7 +321,8 @@ impl TypeBuilder { Self { handle } } - pub(crate) fn as_raw(&self) -> &mut BNTypeBuilder { + #[allow(clippy::mut_from_ref)] + pub(crate) unsafe fn as_raw(&self) -> &mut BNTypeBuilder { unsafe { &mut (*self.handle.as_ptr()) } } @@ -711,7 +712,12 @@ impl Type { Self { handle } } - pub(crate) fn as_raw(&self) -> &mut BNType { + pub(crate) unsafe fn ref_from_raw(handle: &*mut BNType) -> &Self { + mem::transmute(handle) + } + + #[allow(clippy::mut_from_ref)] + pub(crate) unsafe fn as_raw(&self) -> &mut BNType { unsafe { &mut (*self.handle.as_ptr()) } } @@ -1294,6 +1300,13 @@ impl FunctionParameter { (!self.default_location).then_some(self.location) } + pub fn set_location(&mut self, value: Option) { + self.default_location = value.is_none(); + if let Some(var) = value { + self.location = var; + } + } + pub fn name(&self) -> Cow { if let Some(name) = &self.name { Cow::Borrowed(name.as_str()) @@ -1315,6 +1328,10 @@ impl FunctionParameter { } } } + + pub fn set_name(&mut self, value: S) { + self.name = Some(BnString::new(value)); + } } impl CoreArrayProvider for FunctionParameter { @@ -1478,7 +1495,8 @@ impl NamedTypedVariable { mem::transmute(handle) } - pub(crate) fn as_raw(&self) -> &BNVariableNameAndType { + #[allow(clippy::mut_from_ref)] + pub(crate) unsafe fn as_raw(&self) -> &BNVariableNameAndType { unsafe { mem::transmute(self) } } @@ -1580,7 +1598,8 @@ impl EnumerationBuilder { Self { handle } } - pub(crate) fn as_raw(&self) -> &mut BNEnumerationBuilder { + #[allow(clippy::mut_from_ref)] + pub(crate) unsafe fn as_raw(&self) -> &mut BNEnumerationBuilder { unsafe { &mut (*self.handle.as_ptr()) } } @@ -1676,7 +1695,8 @@ impl Enumeration { Self { handle } } - pub(crate) fn as_raw(&self) -> &mut BNEnumeration { + #[allow(clippy::mut_from_ref)] + pub(crate) unsafe fn as_raw(&self) -> &mut BNEnumeration { unsafe { &mut (*self.handle.as_ptr()) } } @@ -1751,7 +1771,8 @@ impl StructureBuilder { Self { handle } } - pub(crate) fn as_raw(&self) -> &mut BNStructureBuilder { + #[allow(clippy::mut_from_ref)] + pub(crate) unsafe fn as_raw(&self) -> &mut BNStructureBuilder { unsafe { &mut (*self.handle.as_ptr()) } } @@ -1991,11 +2012,14 @@ impl From<&Structure> for StructureBuilder { } } -impl From> for StructureBuilder { - fn from(members: Vec) -> StructureBuilder { +impl<'a, I> From for StructureBuilder +where + I: IntoIterator, +{ + fn from(members: I) -> StructureBuilder { let builder = StructureBuilder::new(); for m in members { - builder.insert_member(&m, false); + builder.insert_member(m, false); } builder } @@ -2042,7 +2066,8 @@ impl Structure { Self { handle } } - pub(crate) fn as_raw(&self) -> &mut BNStructure { + #[allow(clippy::mut_from_ref)] + pub(crate) unsafe fn as_raw(&self) -> &mut BNStructure { unsafe { &mut (*self.handle.as_ptr()) } } @@ -2144,6 +2169,11 @@ impl StructureMember { Conf::new(&self.ty, self.type_confidence) } + pub fn set_type(&mut self, value: Conf) { + self.ty = value.contents; + self.type_confidence = value.confidence; + } + pub fn name(&self) -> &str { self.name.as_str() } @@ -2267,7 +2297,8 @@ impl NamedTypeReference { mem::transmute(handle) } - pub(crate) fn as_raw(&self) -> &mut BNNamedTypeReference { + #[allow(clippy::mut_from_ref)] + pub(crate) unsafe fn as_raw(&self) -> &mut BNNamedTypeReference { unsafe { &mut (*self.handle.as_ptr()) } } @@ -2406,7 +2437,8 @@ impl QualifiedName { mem::transmute(handle) } - pub(crate) fn as_raw(&self) -> &BNQualifiedName { + #[allow(clippy::mut_from_ref)] + pub(crate) unsafe fn as_raw(&self) -> &BNQualifiedName { unsafe { mem::transmute(self) } } @@ -2446,6 +2478,12 @@ impl From for QualifiedName { } } +impl From> for QualifiedName { + fn from(names: Vec) -> Self { + names.into_iter().collect() + } +} + impl FromIterator for QualifiedName { fn from_iter>(iter: T) -> Self { let default_join = unsafe { CStr::from_bytes_with_nul_unchecked(b"::\x00") }; @@ -2765,11 +2803,27 @@ pub struct DataVariableAndName { } impl DataVariableAndName { + pub fn new( + address: u64, + t: Conf, + auto_discovered: bool, + name: S, + ) -> Self { + Self { + address, + t: ManuallyDrop::new(t.contents), + name: ManuallyDrop::new(BnString::new(name)), + auto_discovered, + type_confidence: t.confidence, + } + } + pub(crate) unsafe fn ref_from_raw(var: &BNDataVariableAndName) -> &Self { unsafe { mem::transmute(var) } } - pub(crate) fn as_raw(&self) -> &BNDataVariableAndName { + #[allow(clippy::mut_from_ref)] + pub(crate) unsafe fn as_raw(&self) -> &BNDataVariableAndName { unsafe { mem::transmute(self) } } From 44c0d312dfce77ec79ce6ce71602abe87956f407 Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Fri, 31 May 2024 08:10:52 -0300 Subject: [PATCH 29/33] change `StackVariableReference` to the new standard --- rust/src/types.rs | 48 ++++++++++++++++++++--------------------------- 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/rust/src/types.rs b/rust/src/types.rs index 18aef7dff..c0c147b8e 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -3660,47 +3660,39 @@ pub type IntegerDisplayType = binaryninjacore_sys::BNIntegerDisplayType; ///////////////////////// // StackVariableReference +#[repr(C)] #[derive(Debug, Clone)] pub struct StackVariableReference { - _source_operand: u32, - var_type: Conf, + source_operand: u32, + type_confidence: u8, + type_: Type, name: BnString, - var: Variable, - offset: i64, + var_identifier: u64, + referenced_offset: i64, size: usize, } impl StackVariableReference { - pub fn from_raw(value: BNStackVariableReference) -> Self { - let var_type = Conf::new( - unsafe { Type::from_raw(NonNull::new(value.type_).unwrap()) }, - value.typeConfidence, - ); - let name = unsafe { BnString::from_raw(NonNull::new(value.name).unwrap()) }; - let var = unsafe { Variable::from_identifier(value.varIdentifier) }; - let offset = value.referencedOffset; - let size = value.size; - Self { - _source_operand: value.sourceOperand, - var_type, - name, - var, - offset, - size, - } + pub(crate) unsafe fn ref_from_raw(value: &BNStackVariableReference) -> &Self { + mem::transmute(value) } - pub fn variable(&self) -> &Variable { - &self.var + + pub fn variable(&self) -> Variable { + unsafe { Variable::from_identifier(self.var_identifier) } } + pub fn variable_type(&self) -> Conf<&Type> { - self.var_type.as_ref() + Conf::new(&self.type_, self.type_confidence) } + pub fn name(&self) -> &str { self.name.as_str() } + pub fn offset(&self) -> i64 { - self.offset + self.referenced_offset } + pub fn size(&self) -> usize { self.size } @@ -3709,15 +3701,15 @@ impl StackVariableReference { impl CoreArrayProvider for StackVariableReference { type Raw = BNStackVariableReference; type Context = (); - type Wrapped<'a> = Guard<'a, Self>; + type Wrapped<'a> = &'a Self; } unsafe impl CoreArrayProviderInner for StackVariableReference { unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) { BNFreeStackVariableReferenceList(raw, count) } - unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> { - Guard::new(Self::from_raw(*raw), context) + unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> { + Self::ref_from_raw(raw) } } From 03148eb5d89445d36963404f5a4c30f44252701e Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Fri, 31 May 2024 08:13:04 -0300 Subject: [PATCH 30/33] change `IndirectBranchInfo` to the new standard --- rust/src/architecture.rs | 1 + rust/src/types.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/rust/src/architecture.rs b/rust/src/architecture.rs index 6aa16c261..c9b1d938d 100644 --- a/rust/src/architecture.rs +++ b/rust/src/architecture.rs @@ -1059,6 +1059,7 @@ impl Drop for CoreArchitectureList { } } +#[repr(transparent)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct CoreArchitecture(pub(crate) *mut BNArchitecture); diff --git a/rust/src/types.rs b/rust/src/types.rs index c0c147b8e..903062d6c 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -3455,6 +3455,8 @@ unsafe impl CoreArrayProviderInner for ConstantReference { ///////////////////////// // IndirectBranchInfo +#[repr(C)] +#[derive(Debug, Clone, Copy)] pub struct IndirectBranchInfo { pub source_arch: CoreArchitecture, pub source_addr: u64, From 0c9ecbe7d453b53689566a11faca7335e664053a Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Fri, 31 May 2024 08:14:23 -0300 Subject: [PATCH 31/33] change `BNConstantReference` to the new standard --- rust/src/types.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/rust/src/types.rs b/rust/src/types.rs index 903062d6c..59b24ef63 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -3410,6 +3410,7 @@ impl Drop for UserVariableValues { ///////////////////////// // ConstantReference +#[repr(C)] #[derive(Copy, Clone, Eq, Hash, PartialEq)] pub struct ConstantReference { pub value: i64, From 37f168e8f9e19c1dc133404b53a012fa4822bc9a Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Fri, 31 May 2024 08:29:30 -0300 Subject: [PATCH 32/33] change `UserVariableValue` to the new standard --- rust/src/mlil/function.rs | 12 +++--- rust/src/types.rs | 87 +++++++++++++++++++++++++-------------- 2 files changed, 60 insertions(+), 39 deletions(-) diff --git a/rust/src/mlil/function.rs b/rust/src/mlil/function.rs index d9e133138..8c3ce3e23 100644 --- a/rust/src/mlil/function.rs +++ b/rust/src/mlil/function.rs @@ -11,7 +11,7 @@ use crate::function::{Function, Location}; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref, RefCountable}; use crate::string::BnStrCompatible; use crate::types::{ - Conf, PossibleValueSet, RegisterValue, SSAVariable, Type, UserVariableValues, Variable, + Conf, PossibleValueSet, RegisterValue, SSAVariable, Type, UserVariableValue, Variable, }; use super::{MediumLevelILBlock, MediumLevelILInstruction, MediumLevelILLiftedInstruction}; @@ -242,20 +242,18 @@ impl MediumLevelILFunction { /// Returns a map of current defined user variable values. /// Returns a Map of user current defined user variable values and their definition sites. - pub fn user_var_values(&self) -> UserVariableValues { + pub fn user_var_values(&self) -> Array { let mut count = 0; let function = self.get_function(); let var_values = unsafe { BNGetAllUserVariableValues(function.handle, &mut count) }; assert!(!var_values.is_null()); - UserVariableValues { - vars: core::ptr::slice_from_raw_parts(var_values, count), - } + unsafe { Array::new(var_values, count, ()) } } /// Clear all user defined variable values. pub fn clear_user_var_values(&self) -> Result<(), ()> { - for (var, arch_and_addr, _value) in self.user_var_values().all() { - self.clear_user_var_value(&var, arch_and_addr.address)?; + for user_value in self.user_var_values().iter() { + self.clear_user_var_value(&user_value.var, user_value.def_site.address)?; } Ok(()) } diff --git a/rust/src/types.rs b/rust/src/types.rs index 59b24ef63..378c116ed 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -3355,55 +3355,78 @@ impl Drop for LookupTableEntryRaw { ///////////////////////// // ArchAndAddr +#[repr(C)] #[derive(Copy, Clone, Eq, Hash, PartialEq)] pub struct ArchAndAddr { pub arch: CoreArchitecture, pub address: u64, } +impl ArchAndAddr { + pub(crate) unsafe fn from_raw(value: BNArchitectureAndAddress) -> Self { + mem::transmute(value) + } +} + ///////////////////////// -// UserVariableValues +// UserVariableValue + +pub struct UserVariableValue { + pub var: Variable, + pub def_site: ArchAndAddr, + pub possible_value: PossibleValueSet, +} + +impl UserVariableValue { + pub(crate) unsafe fn from_raw(value: BNUserVariableValue) -> Self { + let var = Variable::from_raw(value.var); + let def_site = ArchAndAddr::from_raw(value.defSite); + let value = PossibleValueSet::from_raw(value.value); + Self { + var, + def_site, + possible_value: value, + } + } +} -pub struct UserVariableValues { - pub(crate) vars: *const [BNUserVariableValue], +impl CoreArrayProvider for UserVariableValue { + type Raw = BNUserVariableValue; + type Context = (); + type Wrapped<'a> = Self; } -impl UserVariableValues { - pub fn into_hashmap(self) -> HashMap> { +unsafe impl CoreArrayProviderInner for UserVariableValue { + unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) { + unsafe { BNFreeUserVariableValues(raw) }; + } + + unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> { + Self::from_raw(*raw) + } +} + +impl Array { + pub fn into_hashmap(&self) -> HashMap> { let mut result: HashMap> = HashMap::new(); - for (var, def_site, possible_val) in self.all() { + for value in self.iter() + { result - .entry(var) + .entry(value.var) .or_default() - .entry(def_site) - .or_insert(possible_val); + .entry(value.def_site) + .or_insert(value.possible_value); } result } - pub fn all(&self) -> impl Iterator { - unsafe { &*self.vars }.iter().map(|var_val| { - let var = unsafe { Variable::from_raw(var_val.var) }; - let def_site = ArchAndAddr { - arch: unsafe { CoreArchitecture::from_raw(var_val.defSite.arch) }, - address: var_val.defSite.address, - }; - let possible_val = unsafe { PossibleValueSet::from_raw(var_val.value) }; - (var, def_site, possible_val) - }) - } - pub fn values_from_variable( - &self, - var: Variable, - ) -> impl Iterator { - self.all() - .filter(move |(t_var, _, _)| t_var == &var) - .map(|(_var, def_site, possible_val)| (def_site, possible_val)) - } -} -impl Drop for UserVariableValues { - fn drop(&mut self) { - unsafe { BNFreeUserVariableValues(self.vars as *mut BNUserVariableValue) }; + pub fn values_from_variable<'a>( + &'a self, + var: Variable, + ) -> impl Iterator + 'a { + self.iter() + .filter(move |value| value.var == var) + .map(|value| (value.def_site, value.possible_value)) } } From 5c8e8234b1405c1f96c28e4de4c2365a994c47bc Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Tue, 4 Jun 2024 12:02:55 -0300 Subject: [PATCH 33/33] fix doc --- rust/src/mlil/function.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rust/src/mlil/function.rs b/rust/src/mlil/function.rs index 8c3ce3e23..ffcc1d819 100644 --- a/rust/src/mlil/function.rs +++ b/rust/src/mlil/function.rs @@ -188,10 +188,9 @@ impl MediumLevelILFunction { /// # use binaryninja::mlil::MediumLevelILFunction; /// # use binaryninja::types::PossibleValueSet; /// # let mlil_fun: MediumLevelILFunction = todo!(); - /// let (mlil_var, arch_addr, _val) = mlil_fun.user_var_values().all().next().unwrap(); - /// let def_address = arch_addr.address; + /// let var_val = mlil_fun.user_var_values().get(0); /// let var_value = PossibleValueSet::ConstantValue{value: 5}; - /// mlil_fun.set_user_var_value(&mlil_var, def_address, var_value).unwrap(); + /// mlil_fun.set_user_var_value(&var_val.var, var_val.def_site.address, var_value).unwrap(); /// ``` pub fn set_user_var_value( &self,