Skip to content

Commit 538565e

Browse files
committed
Fix workflow Rust API not returning refcounted objects
IDK why this was not done prior, leaking the returned core activity and workflow object.
1 parent 0f26e92 commit 538565e

File tree

5 files changed

+29
-29
lines changed

5 files changed

+29
-29
lines changed

plugins/svd/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ pub extern "C" fn CorePluginInit() -> bool {
100100

101101
// Register new workflow activity to load svd information.
102102
let old_module_meta_workflow = Workflow::instance("core.module.metaAnalysis");
103-
let module_meta_workflow = old_module_meta_workflow.clone("core.module.metaAnalysis");
103+
let module_meta_workflow = old_module_meta_workflow.clone_to("core.module.metaAnalysis");
104104
let loader_activity = Activity::new_with_action(LOADER_ACTIVITY_CONFIG, loader_activity);
105105
module_meta_workflow
106106
.register_activity(&loader_activity)

plugins/warp/src/plugin/workflow.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ pub fn insert_workflow() {
8080
};
8181

8282
let old_function_meta_workflow = Workflow::instance("core.function.metaAnalysis");
83-
let function_meta_workflow = old_function_meta_workflow.clone("core.function.metaAnalysis");
83+
let function_meta_workflow = old_function_meta_workflow.clone_to("core.function.metaAnalysis");
8484
let guid_activity = Activity::new_with_action(GUID_ACTIVITY_CONFIG, guid_activity);
8585
function_meta_workflow
8686
.register_activity(&guid_activity)
@@ -89,7 +89,7 @@ pub fn insert_workflow() {
8989
function_meta_workflow.register().unwrap();
9090

9191
let old_module_meta_workflow = Workflow::instance("core.module.metaAnalysis");
92-
let module_meta_workflow = old_module_meta_workflow.clone("core.module.metaAnalysis");
92+
let module_meta_workflow = old_module_meta_workflow.clone_to("core.module.metaAnalysis");
9393
let matcher_activity = Activity::new_with_action(MATCHER_ACTIVITY_CONFIG, matcher_activity);
9494
module_meta_workflow
9595
.register_activity(&matcher_activity)

rust/examples/workflow.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ pub fn main() {
5353

5454
println!("Registering workflow...");
5555
let old_meta_workflow = Workflow::instance("core.function.metaAnalysis");
56-
let meta_workflow = old_meta_workflow.clone("core.function.metaAnalysis");
56+
let meta_workflow = old_meta_workflow.clone_to("core.function.metaAnalysis");
5757
let activity = Activity::new_with_action(RUST_ACTIVITY_CONFIG, example_activity);
5858
meta_workflow.register_activity(&activity).unwrap();
5959
meta_workflow.insert("core.function.runFunctionRecognizers", [RUST_ACTIVITY_NAME]);

rust/src/workflow.rs

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -164,16 +164,16 @@ pub struct Activity {
164164
}
165165

166166
impl Activity {
167+
#[allow(unused)]
167168
pub(crate) unsafe fn from_raw(handle: NonNull<BNActivity>) -> Self {
168169
Self { handle }
169170
}
170-
171-
#[allow(unused)]
171+
172172
pub(crate) unsafe fn ref_from_raw(handle: NonNull<BNActivity>) -> Ref<Self> {
173173
Ref::new(Self { handle })
174174
}
175175

176-
pub fn new<S: BnStrCompatible>(config: S) -> Self {
176+
pub fn new<S: BnStrCompatible>(config: S) -> Ref<Self> {
177177
unsafe extern "C" fn cb_action_nop(_: *mut c_void, _: *mut BNAnalysisContext) {}
178178
let config = config.into_bytes_with_nul();
179179
let result = unsafe {
@@ -183,10 +183,10 @@ impl Activity {
183183
Some(cb_action_nop),
184184
)
185185
};
186-
unsafe { Activity::from_raw(NonNull::new(result).unwrap()) }
186+
unsafe { Activity::ref_from_raw(NonNull::new(result).unwrap()) }
187187
}
188188

189-
pub fn new_with_action<S, F>(config: S, mut action: F) -> Self
189+
pub fn new_with_action<S, F>(config: S, mut action: F) -> Ref<Self>
190190
where
191191
S: BnStrCompatible,
192192
F: FnMut(&AnalysisContext),
@@ -208,7 +208,7 @@ impl Activity {
208208
Some(cb_action::<F>),
209209
)
210210
};
211-
unsafe { Activity::from_raw(NonNull::new(result).unwrap()) }
211+
unsafe { Activity::ref_from_raw(NonNull::new(result).unwrap()) }
212212
}
213213

214214
pub fn name(&self) -> BnString {
@@ -256,35 +256,35 @@ impl Workflow {
256256

257257
/// Create a new unregistered [Workflow] with no activities.
258258
///
259-
/// To get a copy of an existing registered [Workflow] use [Workflow::clone].
260-
pub fn new<S: BnStrCompatible>(name: S) -> Self {
259+
/// To get a copy of an existing registered [Workflow] use [Workflow::clone_to].
260+
pub fn new<S: BnStrCompatible>(name: S) -> Ref<Self> {
261261
let name = name.into_bytes_with_nul();
262262
let result = unsafe { BNCreateWorkflow(name.as_ref().as_ptr() as *const c_char) };
263-
unsafe { Workflow::from_raw(NonNull::new(result).unwrap()) }
263+
unsafe { Workflow::ref_from_raw(NonNull::new(result).unwrap()) }
264264
}
265265

266266
/// Make a new unregistered [Workflow], copying all activities and the execution strategy.
267267
///
268268
/// * `name` - the name for the new [Workflow]
269269
#[must_use]
270-
pub fn clone<S: BnStrCompatible + Clone>(&self, name: S) -> Workflow {
271-
self.clone_with_root(name, "")
270+
pub fn clone_to<S: BnStrCompatible + Clone>(&self, name: S) -> Ref<Workflow> {
271+
self.clone_to_with_root(name, "")
272272
}
273273

274274
/// Make a new unregistered [Workflow], copying all activities, within `root_activity`, and the execution strategy.
275275
///
276276
/// * `name` - the name for the new [Workflow]
277277
/// * `root_activity` - perform the clone operation with this activity as the root
278278
#[must_use]
279-
pub fn clone_with_root<S: BnStrCompatible, A: BnStrCompatible>(
279+
pub fn clone_to_with_root<S: BnStrCompatible, A: BnStrCompatible>(
280280
&self,
281281
name: S,
282282
root_activity: A,
283-
) -> Workflow {
283+
) -> Ref<Workflow> {
284284
let raw_name = name.into_bytes_with_nul();
285285
let activity = root_activity.into_bytes_with_nul();
286286
unsafe {
287-
Self::from_raw(
287+
Self::ref_from_raw(
288288
NonNull::new(BNWorkflowClone(
289289
self.handle.as_ptr(),
290290
raw_name.as_ref().as_ptr() as *const c_char,
@@ -295,11 +295,11 @@ impl Workflow {
295295
}
296296
}
297297

298-
pub fn instance<S: BnStrCompatible>(name: S) -> Workflow {
298+
pub fn instance<S: BnStrCompatible>(name: S) -> Ref<Workflow> {
299299
let result = unsafe {
300300
BNWorkflowInstance(name.into_bytes_with_nul().as_ref().as_ptr() as *const c_char)
301301
};
302-
unsafe { Workflow::from_raw(NonNull::new(result).unwrap()) }
302+
unsafe { Workflow::ref_from_raw(NonNull::new(result).unwrap()) }
303303
}
304304

305305
/// List of all registered [Workflow]'s
@@ -341,7 +341,7 @@ impl Workflow {
341341
/// Register an [Activity] with this Workflow.
342342
///
343343
/// * `activity` - the [Activity] to register
344-
pub fn register_activity(&self, activity: &Activity) -> Result<Activity, ()> {
344+
pub fn register_activity(&self, activity: &Activity) -> Result<Ref<Activity>, ()> {
345345
self.register_activity_with_subactivities::<Vec<String>>(activity, vec![])
346346
}
347347

@@ -353,7 +353,7 @@ impl Workflow {
353353
&self,
354354
activity: &Activity,
355355
subactivities: I,
356-
) -> Result<Activity, ()>
356+
) -> Result<Ref<Activity>, ()>
357357
where
358358
I: IntoIterator,
359359
I::Item: BnStrCompatible,
@@ -375,7 +375,7 @@ impl Workflow {
375375
)
376376
};
377377
let activity_ptr = NonNull::new(result).ok_or(())?;
378-
unsafe { Ok(Activity::from_raw(activity_ptr)) }
378+
unsafe { Ok(Activity::ref_from_raw(activity_ptr)) }
379379
}
380380

381381
/// Determine if an Activity exists in this [Workflow].
@@ -418,15 +418,15 @@ impl Workflow {
418418
}
419419

420420
/// Retrieve the Activity object for the specified `name`.
421-
pub fn activity<A: BnStrCompatible>(&self, name: A) -> Option<Activity> {
421+
pub fn activity<A: BnStrCompatible>(&self, name: A) -> Option<Ref<Activity>> {
422422
let name = name.into_bytes_with_nul();
423423
let result = unsafe {
424424
BNWorkflowGetActivity(
425425
self.handle.as_ptr(),
426426
name.as_ref().as_ptr() as *const c_char,
427427
)
428428
};
429-
NonNull::new(result).map(|a| unsafe { Activity::from_raw(a) })
429+
NonNull::new(result).map(|a| unsafe { Activity::ref_from_raw(a) })
430430
}
431431

432432
/// Retrieve the list of activity roots for the [Workflow], or if

rust/tests/workflow.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ use binaryninja::workflow::Workflow;
99
fn test_workflow_clone() {
1010
let _session = Session::new().expect("Failed to initialize session");
1111
let original_workflow = Workflow::new("core.function.baseAnalysis");
12-
let mut cloned_workflow = original_workflow.clone("clone_workflow");
12+
let mut cloned_workflow = original_workflow.clone_to("clone_workflow");
1313

1414
assert_eq!(cloned_workflow.name().as_str(), "clone_workflow");
1515
assert_eq!(
1616
cloned_workflow.configuration(),
1717
original_workflow.configuration()
1818
);
1919

20-
cloned_workflow = original_workflow.clone("");
20+
cloned_workflow = original_workflow.clone_to("");
2121
assert_eq!(
2222
cloned_workflow.name().as_str(),
2323
"core.function.baseAnalysis"
@@ -36,7 +36,7 @@ fn test_workflow_registration() {
3636
.expect_err("Re-registration of null is allowed");
3737

3838
// Validate new workflows can be registered
39-
let test_workflow = Workflow::instance("core.function.baseAnalysis").clone("test_workflow");
39+
let test_workflow = Workflow::instance("core.function.baseAnalysis").clone_to("test_workflow");
4040

4141
assert_eq!(test_workflow.name().as_str(), "test_workflow");
4242
assert!(!test_workflow.registered());
@@ -66,7 +66,7 @@ fn test_workflow_registration() {
6666
assert!(!Workflow::instance("core.function.baseAnalysis").clear());
6767

6868
// Validate re-registration of baseAnalysis is not allowed
69-
let base_workflow_clone = Workflow::instance("core.function.baseAnalysis").clone("");
69+
let base_workflow_clone = Workflow::instance("core.function.baseAnalysis").clone_to("");
7070

7171
assert_eq!(
7272
base_workflow_clone.name().as_str(),

0 commit comments

Comments
 (0)