diff options
| author | Brian Potchik <brian@vector35.com> | 2025-03-06 19:54:50 -0500 |
|---|---|---|
| committer | Brian Potchik <brian@vector35.com> | 2025-03-06 19:54:50 -0500 |
| commit | ef97d4703cfd08a4ccc3c00dac7cf84877875245 (patch) | |
| tree | d8687be219e325cd619ada7acfaf694a6627af1c | |
| parent | 5192206454838298978583761915446906174711 (diff) | |
Add API to insert Activities after a specified Activity.
| -rw-r--r-- | binaryninjaapi.h | 16 | ||||
| -rw-r--r-- | binaryninjacore.h | 3 | ||||
| -rw-r--r-- | python/workflow.py | 20 | ||||
| -rw-r--r-- | rust/src/workflow.rs | 28 | ||||
| -rw-r--r-- | workflow.cpp | 29 |
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()); |
