summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Potchik <brian@vector35.com>2025-03-06 19:54:50 -0500
committerBrian Potchik <brian@vector35.com>2025-03-06 19:54:50 -0500
commitef97d4703cfd08a4ccc3c00dac7cf84877875245 (patch)
treed8687be219e325cd619ada7acfaf694a6627af1c
parent5192206454838298978583761915446906174711 (diff)
Add API to insert Activities after a specified Activity.
-rw-r--r--binaryninjaapi.h16
-rw-r--r--binaryninjacore.h3
-rw-r--r--python/workflow.py20
-rw-r--r--rust/src/workflow.rs28
-rw-r--r--workflow.cpp29
5 files changed, 94 insertions, 2 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index a0ad6980..08e3feb5 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -10213,6 +10213,22 @@ namespace BinaryNinja {
*/
bool Insert(const std::string& activity, const std::vector<std::string>& activities);
+ /*! Insert an activity after the specified activity and at the same level.
+
+ \param activity Name of the activity to insert the new one after
+ \param newActivity Name of the new activity to be inserted
+ \return true on success, false otherwise
+ */
+ bool InsertAfter(const std::string& activity, const std::string& newActivity);
+
+ /*! Insert a list of activities after the specified activity and at the same level.
+
+ \param activity Name of the activity to insert the new one after
+ \param newActivity Name of the new activities to be inserted
+ \return true on success, false otherwise
+ */
+ bool InsertAfter(const std::string& activity, const std::vector<std::string>& activities);
+
/*! Remove an activity by name
\param activity Name of the activity to remove
diff --git a/binaryninjacore.h b/binaryninjacore.h
index 97e7c52a..55b5c2be 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -37,7 +37,7 @@
// Current ABI version for linking to the core. This is incremented any time
// there are changes to the API that affect linking, including new functions,
// new types, or modifications to existing functions or types.
-#define BN_CURRENT_CORE_ABI_VERSION 97
+#define BN_CURRENT_CORE_ABI_VERSION 98
// Minimum ABI version that is supported for loading of plugins. Plugins that
// are linked to an ABI version less than this will not be able to load and
@@ -5508,6 +5508,7 @@ extern "C"
BINARYNINJACOREAPI bool BNWorkflowAssignSubactivities(BNWorkflow* workflow, const char* activity, const char** activities, size_t size);
BINARYNINJACOREAPI bool BNWorkflowClear(BNWorkflow* workflow);
BINARYNINJACOREAPI bool BNWorkflowInsert(BNWorkflow* workflow, const char* activity, const char** activities, size_t size);
+ BINARYNINJACOREAPI bool BNWorkflowInsertAfter(BNWorkflow* workflow, const char* activity, const char** activities, size_t size);
BINARYNINJACOREAPI bool BNWorkflowRemove(BNWorkflow* workflow, const char* activity);
BINARYNINJACOREAPI bool BNWorkflowReplace(BNWorkflow* workflow, const char* activity, const char* newActivity);
diff --git a/python/workflow.py b/python/workflow.py
index 7eed81c1..063321af 100644
--- a/python/workflow.py
+++ b/python/workflow.py
@@ -487,7 +487,7 @@ class Workflow(metaclass=_WorkflowMetaclass):
"""
return core.BNWorkflowClear(self.handle)
- def insert(self, activity: ActivityType, activities: List[str]) -> bool:
+ def insert(self, activity: ActivityType, activities: Union[List[str], str]) -> bool:
"""
``insert`` Insert the list of ``activities`` before the specified ``activity`` and at the same level.
@@ -496,11 +496,29 @@ class Workflow(metaclass=_WorkflowMetaclass):
:return: True on success, False otherwise
:rtype: bool
"""
+ if isinstance(activities, str):
+ activities = [activities]
input_list = (ctypes.c_char_p * len(activities))()
for i in range(0, len(activities)):
input_list[i] = str(activities[i]).encode('charmap')
return core.BNWorkflowInsert(self.handle, str(activity), input_list, len(activities))
+ def insert_after(self, activity: ActivityType, activities: Union[List[str], str]) -> bool:
+ """
+ ``insert_after`` Insert the list of ``activities`` after the specified ``activity`` and at the same level.
+
+ :param str activity: the Activity node for which to insert ``activities`` after
+ :param list[str] activities: the list of Activities to insert
+ :return: True on success, False otherwise
+ :rtype: bool
+ """
+ if isinstance(activities, str):
+ activities = [activities]
+ input_list = (ctypes.c_char_p * len(activities))()
+ for i in range(0, len(activities)):
+ input_list[i] = str(activities[i]).encode('charmap')
+ return core.BNWorkflowInsertAfter(self.handle, str(activity), input_list, len(activities))
+
def remove(self, activity: ActivityType) -> bool:
"""
``remove`` Remove the specified ``activity``.
diff --git a/rust/src/workflow.rs b/rust/src/workflow.rs
index e95beb48..dcc388d9 100644
--- a/rust/src/workflow.rs
+++ b/rust/src/workflow.rs
@@ -529,6 +529,34 @@ impl Workflow {
}
}
+ /// Insert the list of `activities` after the specified `activity` and at the same level.
+ ///
+ /// * `activity` - the Activity node for which to insert `activities` after
+ /// * `activities` - the list of Activities to insert
+ pub fn insert_after<A, I>(&self, activity: A, activities: I) -> bool
+ where
+ A: BnStrCompatible,
+ I: IntoIterator,
+ I::Item: BnStrCompatible,
+ {
+ let input_list: Vec<_> = activities
+ .into_iter()
+ .map(|a| a.into_bytes_with_nul())
+ .collect();
+ let mut input_list_ptr: Vec<*const _> = input_list
+ .iter()
+ .map(|x| x.as_ref().as_ptr() as *const c_char)
+ .collect();
+ unsafe {
+ BNWorkflowInsertAfter(
+ self.handle.as_ptr(),
+ activity.into_bytes_with_nul().as_ref().as_ptr() as *const c_char,
+ input_list_ptr.as_mut_ptr(),
+ input_list.len(),
+ )
+ }
+ }
+
/// Remove the specified `activity`
pub fn remove<A: BnStrCompatible>(&self, activity: A) -> bool {
unsafe {
diff --git a/workflow.cpp b/workflow.cpp
index 135c029f..3e43707e 100644
--- a/workflow.cpp
+++ b/workflow.cpp
@@ -415,6 +415,35 @@ bool Workflow::Insert(const string& activity, const vector<string>& activities)
}
+bool Workflow::InsertAfter(const string& activity, const string& newActivity)
+{
+ char* buffer[1];
+ buffer[0] = BNAllocString(newActivity.c_str());
+
+ bool result = BNWorkflowInsertAfter(m_object, activity.c_str(), (const char**)buffer, 1);
+ BNFreeString(buffer[0]);
+ return result;
+}
+
+
+bool Workflow::InsertAfter(const string& activity, const vector<string>& activities)
+{
+ char** buffer = new char*[activities.size()];
+ if (!buffer)
+ return false;
+
+ for (size_t i = 0; i < activities.size(); i++)
+ buffer[i] = BNAllocString(activities[i].c_str());
+
+ bool result = BNWorkflowInsertAfter(m_object, activity.c_str(), (const char**)buffer, activities.size());
+
+ for (size_t i = 0; i < activities.size(); i++)
+ BNFreeString(buffer[i]);
+ delete[] buffer;
+ return result;
+}
+
+
bool Workflow::Remove(const string& activity)
{
return BNWorkflowRemove(m_object, activity.c_str());