Skip to content

Commit 3551171

Browse files
committed
remove the use of Box in data_notification
1 parent 3ab4cb0 commit 3551171

File tree

2 files changed

+27
-43
lines changed

2 files changed

+27
-43
lines changed

rust/src/data_notification.rs

Lines changed: 18 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use core::ffi;
2+
use core::pin::Pin;
23
use core::ptr;
34
use std::ffi::CStr;
45

@@ -40,7 +41,7 @@ macro_rules! trait_handler {
4041
/// Used to describe which call should be triggered by BinaryNinja.
4142
/// By default all calls are disabled.
4243
///
43-
/// Used by [CustomDataNotification::register]
44+
/// Used by [CustomDataNotification::register] and [register_data_notification].
4445
#[derive(Default)]
4546
pub struct DataNotificationTriggers {
4647
$($fun_name: bool,)*
@@ -62,12 +63,16 @@ macro_rules! trait_handler {
6263
}
6364
)*
6465

66+
/// Register the data notification functions.
67+
///
68+
/// If the type don't implement Unpin, use the function
69+
/// [register_data_notification] with the pinned value.
6570
fn register<'a>(
66-
self,
71+
&'a mut self,
6772
view: &BinaryView,
6873
triggers: DataNotificationTriggers,
69-
) -> DataNotificationHandle<'a, Self> where Self: 'a + Sized {
70-
register_data_notification(view, self, triggers)
74+
) -> DataNotificationHandle<'a, Self> where Self: 'a + Sized + Unpin {
75+
register_data_notification(view, Pin::new(self), triggers)
7176
}
7277
}
7378
$(
@@ -79,15 +84,14 @@ macro_rules! trait_handler {
7984
handle.$fun_name($($value_calculated),*)
8085
}
8186
)*
82-
fn register_data_notification<'a, H: CustomDataNotification + 'a>(
87+
pub fn register_data_notification<'a, H: 'a + CustomDataNotification>(
8388
view: &BinaryView,
84-
notify: H,
89+
notify: Pin<&'a H>,
8590
triggers: DataNotificationTriggers,
8691
) -> DataNotificationHandle<'a, H> {
87-
// SAFETY: this leak is undone on drop
88-
let leak_notify = Box::leak(Box::new(notify));
92+
let notify = unsafe { Pin::into_inner_unchecked(notify) as *const H };
8993
let mut handle = BNBinaryDataNotification {
90-
context: leak_notify as *mut _ as *mut ffi::c_void,
94+
context: notify as *const ffi::c_void as *mut ffi::c_void,
9195
$($ffi_param_name: triggers.$fun_name.then_some($fun_name::<H>)),*
9296
};
9397
unsafe { BNRegisterDataNotification(view.handle, &mut handle) };
@@ -140,7 +144,7 @@ macro_rules! trait_handler {
140144
)*
141145

142146
pub fn register(
143-
self,
147+
&'a self,
144148
view: &BinaryView,
145149
) -> DataNotificationHandle<'a, Self> {
146150
let mut triggers = DataNotificationTriggers::default();
@@ -149,7 +153,7 @@ macro_rules! trait_handler {
149153
triggers = triggers.$fun_name();
150154
}
151155
)*
152-
register_data_notification(view, self, triggers)
156+
register_data_notification(view, Pin::new(self), triggers)
153157
}
154158
}
155159

@@ -402,36 +406,14 @@ trait_handler! {
402406
),
403407
}
404408

405-
pub struct DataNotificationHandle<'a, T: CustomDataNotification>
406-
where
407-
T: 'a,
408-
{
409+
pub struct DataNotificationHandle<'a, T> {
409410
bv: Ref<BinaryView>,
410411
handle: BNBinaryDataNotification,
411412
_life: std::marker::PhantomData<&'a T>,
412413
}
413414

414-
impl<T: CustomDataNotification> DataNotificationHandle<'_, T> {
415-
unsafe fn unregister_bv(&mut self) {
416-
BNUnregisterDataNotification(self.bv.handle, &mut self.handle)
417-
}
418-
419-
unsafe fn extract_context(&mut self) -> Box<T> {
420-
Box::from_raw(self.handle.context as *mut T)
421-
}
422-
423-
pub fn unregister(self) -> T {
424-
// NOTE don't drop the ctxt, return it
425-
let mut slf = core::mem::ManuallyDrop::new(self);
426-
unsafe { slf.unregister_bv() };
427-
unsafe { *slf.extract_context() }
428-
}
429-
}
430-
431-
impl<T: CustomDataNotification> Drop for DataNotificationHandle<'_, T> {
415+
impl<'a, T> Drop for DataNotificationHandle<'a, T> {
432416
fn drop(&mut self) {
433-
unsafe { self.unregister_bv() };
434-
// drop context, avoid memory leak
435-
let _ctxt = unsafe { self.extract_context() };
417+
unsafe { BNUnregisterDataNotification(self.bv.handle, &mut self.handle) }
436418
}
437419
}

rust/tests/data_notification.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@ fn test_data_notification_dyn_closure() {
1313
let bv = binaryninja::load(out_dir.join("atox.obj")).expect("Failed to create view");
1414

1515
let mut func_updated_count = 0usize;
16-
let custom = DataNotificationClosure::default()
17-
.function_updated(|_bv: &BinaryView, _func: &Function| {
16+
let custom = DataNotificationClosure::default().function_updated(
17+
|_bv: &BinaryView, _func: &Function| {
1818
func_updated_count += 1;
19-
})
20-
.register(&bv);
19+
},
20+
);
21+
custom.register(&bv);
2122

2223
let funcs = bv.functions();
2324
for func in &funcs {
@@ -30,7 +31,7 @@ fn test_data_notification_dyn_closure() {
3031
None,
3132
);
3233
}
33-
custom.unregister();
34+
drop(custom);
3435

3536
assert_eq!(funcs.len(), func_updated_count);
3637
}
@@ -53,15 +54,16 @@ fn test_data_notification_impl() {
5354
}
5455

5556
let triggers = DataNotificationTriggers::default().tag_added();
56-
let tags_lock = Tag::default().register(&bv, triggers);
57+
let mut tags = Tag::default();
58+
let tags_lock = tags.register(&bv, triggers);
5759

5860
let funcs = bv.functions();
5961
for (i, func) in funcs.iter().enumerate() {
6062
let crash = bv.create_tag_type("Test", "🚧");
6163
func.add_tag(&crash, "Dummy tag", Some(i.try_into().unwrap()), true, None);
6264
}
6365

64-
let tags = tags_lock.unregister();
66+
drop(tags_lock);
6567

6668
assert_eq!(funcs.len(), tags.tags);
6769
}

0 commit comments

Comments
 (0)