summaryrefslogtreecommitdiff
path: root/plugins/warp
diff options
context:
space:
mode:
authorMason Reed <35282038+emesare@users.noreply.github.com>2026-02-22 20:40:28 -0800
committerGitHub <noreply@github.com>2026-02-22 20:40:28 -0800
commit017349bdbe171c66974a5835f2f74f76138386ea (patch)
tree2e81f92e683f4b1d12c129360c788e0e52217d82 /plugins/warp
parente2e420c91147f2a83cf59b37c973f57e209ef67a (diff)
[WARP] Allow containers to be constructed programmatically (#7952)
Diffstat (limited to 'plugins/warp')
-rw-r--r--plugins/warp/api/python/warp.py7
-rw-r--r--plugins/warp/api/warp.cpp8
-rw-r--r--plugins/warp/api/warp.h3
-rw-r--r--plugins/warp/api/warpcore.h1
-rw-r--r--plugins/warp/src/cache/container.rs5
-rw-r--r--plugins/warp/src/plugin/ffi/container.rs19
6 files changed, 42 insertions, 1 deletions
diff --git a/plugins/warp/api/python/warp.py b/plugins/warp/api/python/warp.py
index fc487a4d..a699ebbc 100644
--- a/plugins/warp/api/python/warp.py
+++ b/plugins/warp/api/python/warp.py
@@ -351,6 +351,13 @@ class WarpContainer(metaclass=_WarpContainerMetaclass):
return result
@staticmethod
+ def add(name: str) -> 'WarpContainer':
+ container = warpcore.BNWARPAddContainer(name)
+ if container is None:
+ raise ValueError(f"Failed to add container: {name}")
+ return WarpContainer(container)
+
+ @staticmethod
def by_name(name: str) -> Optional['WarpContainer']:
for container in WarpContainer:
if container.name == name:
diff --git a/plugins/warp/api/warp.cpp b/plugins/warp/api/warp.cpp
index f6106605..c051e3c7 100644
--- a/plugins/warp/api/warp.cpp
+++ b/plugins/warp/api/warp.cpp
@@ -246,6 +246,14 @@ std::vector<Ref<Container> > Container::All()
return result;
}
+Ref<Container> Container::Add(const std::string &name)
+{
+ BNWARPContainer *result = BNWARPAddContainer(name.c_str());
+ if (!result)
+ return nullptr;
+ return new Container(result);
+}
+
std::string Container::GetName() const
{
char *rawName = BNWARPContainerGetName(m_object);
diff --git a/plugins/warp/api/warp.h b/plugins/warp/api/warp.h
index 14be9a0d..01f4aaee 100644
--- a/plugins/warp/api/warp.h
+++ b/plugins/warp/api/warp.h
@@ -381,6 +381,9 @@ namespace Warp {
/// Retrieve all available containers.
static std::vector<Ref<Container> > All();
+ /// Add a new container with the given name.
+ static Ref<Container> Add(const std::string &name);
+
std::string GetName() const;
std::vector<Source> GetSources() const;
diff --git a/plugins/warp/api/warpcore.h b/plugins/warp/api/warpcore.h
index 633ffcbf..c52485aa 100644
--- a/plugins/warp/api/warpcore.h
+++ b/plugins/warp/api/warpcore.h
@@ -111,6 +111,7 @@ extern "C"
WARP_FFI_API BNWARPFunction* BNWARPGetFunction(BNFunction* analysisFunction);
WARP_FFI_API BNWARPFunction* BNWARPGetMatchedFunction(BNFunction* analysisFunction);
WARP_FFI_API BNWARPContainer** BNWARPGetContainers(size_t* count);
+ WARP_FFI_API BNWARPContainer* BNWARPAddContainer(const char* name);
WARP_FFI_API char* BNWARPContainerGetName(BNWARPContainer* container);
diff --git a/plugins/warp/src/cache/container.rs b/plugins/warp/src/cache/container.rs
index 0b478ed1..99746d9a 100644
--- a/plugins/warp/src/cache/container.rs
+++ b/plugins/warp/src/cache/container.rs
@@ -35,3 +35,8 @@ pub fn cached_containers() -> Vec<Arc<RwLock<Box<dyn Container>>>> {
let containers_cache = CONTAINER_CACHE.get_or_init(Default::default);
containers_cache.iter().map(|c| c.clone()).collect()
}
+
+pub fn cached_container_by_name(name: &str) -> Option<Arc<RwLock<Box<dyn Container>>>> {
+ let containers_cache = CONTAINER_CACHE.get_or_init(Default::default);
+ containers_cache.get(name).map(|c| c.clone())
+}
diff --git a/plugins/warp/src/plugin/ffi/container.rs b/plugins/warp/src/plugin/ffi/container.rs
index 2376ef10..a107a785 100644
--- a/plugins/warp/src/plugin/ffi/container.rs
+++ b/plugins/warp/src/plugin/ffi/container.rs
@@ -1,4 +1,5 @@
-use crate::cache::container::cached_containers;
+use crate::cache::container::{add_cached_container, cached_container_by_name, cached_containers};
+use crate::container::disk::DiskContainer;
use crate::container::{
ContainerSearchItem, ContainerSearchItemKind, ContainerSearchQuery, SourcePath, SourceTag,
};
@@ -12,6 +13,7 @@ use binaryninja::rc::Ref;
use binaryninja::string::BnString;
use binaryninja::types::Type;
use binaryninjacore_sys::{BNArchitecture, BNBinaryView, BNType};
+use std::collections::HashMap;
use std::ffi::{c_char, CStr};
use std::mem::ManuallyDrop;
use std::ops::Deref;
@@ -173,6 +175,21 @@ pub unsafe extern "C" fn BNWARPContainerSearchItemGetFunction(
}
#[no_mangle]
+pub unsafe extern "C" fn BNWARPAddContainer(name: *const c_char) -> *mut BNWARPContainer {
+ let name_cstr = unsafe { CStr::from_ptr(name) };
+ let name_str = name_cstr.to_str().unwrap();
+ // TODO: Using this generic API name for disk container, I think anything like the network container
+ // TODO: should probably be a second class name so something like BNWARPAddNetworkContainer.
+ let disk_container = DiskContainer::new(name_str.to_string(), HashMap::new());
+ let container_name = disk_container.to_string();
+ add_cached_container(disk_container);
+ match cached_container_by_name(&container_name) {
+ Some(container) => Arc::into_raw(container) as *mut BNWARPContainer,
+ None => std::ptr::null_mut(),
+ }
+}
+
+#[no_mangle]
pub unsafe extern "C" fn BNWARPGetContainers(count: *mut usize) -> *mut *mut BNWARPContainer {
// NOTE: Leak the arc pointers to be freed by BNWARPFreeContainerList
let boxed_raw_containers: Box<[_]> =