summaryrefslogtreecommitdiff
path: root/rust/src/string.rs
diff options
context:
space:
mode:
authorRyan Snyder <ryan@vector35.com>2021-01-21 18:27:48 +0000
committerKyleMiles <krm504@nyu.edu>2021-01-21 19:06:55 +0000
commitd3140edec185f47235b9e4642bdd56d6c585a341 (patch)
treea61859c29e4e3539daea2b761bb1439d942beaf4 /rust/src/string.rs
parentc0ddbf0c76d3f1bb7a2b2024f749afc8b9482575 (diff)
This is a combination of 23 commits, the work of Ryan Snyder:
Initial fresh repo Add support for recent calling convention API updates and folds the binaryninjacore-sys crate directly into this one. Add support for auto function analysis suppression Finish moving binaryninjacore-sys back into this crate Update for Symbol/Segment core API changes Update for Symbol API cleanup api: advance submodule reference, support Token changes arch/lifting: support for flags in custom architectures arch/lifting: support default flag write behaviors, handle more ops build: enable headless binary support on MacOS via evil hack bv: add BinaryView wrapper support, remove wrong comment api: update to latest binja dev branch support deps: bump dep versions rust: bump to 2018 edition api: bump to avoid cargo submodule brokenness build: improve binaryninja path detection; enable linux linkhack bv: stub for bv load settings arch: fix flag related crash, minor llil update api: update for recent changes macos: disable linkhack briefly
Diffstat (limited to 'rust/src/string.rs')
-rw-r--r--rust/src/string.rs201
1 files changed, 201 insertions, 0 deletions
diff --git a/rust/src/string.rs b/rust/src/string.rs
new file mode 100644
index 00000000..1b2e0913
--- /dev/null
+++ b/rust/src/string.rs
@@ -0,0 +1,201 @@
+use std::fmt;
+use std::borrow::Borrow;
+use std::ops::Deref;
+use std::ffi::{CStr, CString};
+use std::os::raw;
+use std::mem;
+
+use crate::rc::*;
+
+#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[repr(C)]
+pub struct BnStr {
+ raw: [u8]
+}
+
+impl BnStr {
+ pub(crate) unsafe fn from_raw<'a>(ptr: *const raw::c_char) -> &'a Self {
+ mem::transmute(CStr::from_ptr(ptr).to_bytes_with_nul())
+ }
+
+ pub fn as_str(&self) -> &str {
+ self.as_cstr().to_str().unwrap()
+ }
+
+ pub fn as_cstr(&self) -> &CStr {
+ unsafe { CStr::from_bytes_with_nul_unchecked(&self.raw) }
+ }
+}
+
+impl Deref for BnStr {
+ type Target = str;
+
+ fn deref(&self) -> &str {
+ self.as_str()
+ }
+}
+
+impl AsRef<[u8]> for BnStr {
+ fn as_ref(&self) -> &[u8] {
+ &self.raw
+ }
+}
+
+impl AsRef<str> for BnStr {
+ fn as_ref(&self) -> &str {
+ self.as_str()
+ }
+}
+
+impl Borrow<str> for BnStr {
+ fn borrow(&self) -> &str {
+ self.as_str()
+ }
+}
+
+impl fmt::Display for BnStr {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.as_cstr().to_string_lossy())
+ }
+}
+
+#[repr(C)]
+pub struct BnString {
+ raw: *mut raw::c_char,
+}
+
+/// A nul-terminated C string allocated by the core.
+///
+/// Received from a variety of core function calls, and
+/// must be used when giving strings to the core from many
+/// core-invoked callbacks.
+impl BnString {
+ pub fn new<S: BnStrCompatible>(s: S) -> Self {
+ use binaryninjacore_sys::BNAllocString;
+
+ let raw = s.as_bytes_with_nul();
+
+ unsafe {
+ let ptr = raw.as_ref().as_ptr() as *mut _;
+
+ Self { raw: BNAllocString(ptr) }
+ }
+ }
+
+ pub(crate) unsafe fn from_raw(raw: *mut raw::c_char) -> Self {
+ Self { raw }
+ }
+
+ pub(crate) fn into_raw(self) -> *mut raw::c_char {
+ let res = self.raw;
+
+ // we're surrendering ownership over the *mut c_char to
+ // the core, so ensure we don't free it
+ mem::forget(self);
+
+ res
+ }
+}
+
+impl Drop for BnString {
+ fn drop(&mut self) {
+ use binaryninjacore_sys::BNFreeString;
+
+ unsafe {
+ BNFreeString(self.raw);
+ }
+ }
+}
+
+impl Deref for BnString {
+ type Target = BnStr;
+
+ fn deref(&self) -> &BnStr {
+ unsafe { BnStr::from_raw(self.raw) }
+ }
+}
+
+impl AsRef<[u8]> for BnString {
+ fn as_ref(&self) -> &[u8] {
+ self.as_cstr().to_bytes_with_nul()
+ }
+}
+
+impl fmt::Display for BnString {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.as_cstr().to_string_lossy())
+ }
+}
+
+unsafe impl CoreOwnedArrayProvider for BnString {
+ type Raw = *mut raw::c_char;
+ type Context = ();
+
+ unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
+ use binaryninjacore_sys::BNFreeStringList;
+ BNFreeStringList(raw, count);
+ }
+}
+
+unsafe impl<'a> CoreOwnedArrayWrapper<'a> for BnString {
+ type Wrapped = &'a BnStr;
+
+ unsafe fn wrap_raw(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped {
+ BnStr::from_raw(*raw)
+ }
+}
+
+pub unsafe trait BnStrCompatible {
+ type Result: AsRef<[u8]>;
+ fn as_bytes_with_nul(self) -> Self::Result;
+}
+
+unsafe impl<'a> BnStrCompatible for &'a BnStr {
+ type Result = &'a [u8];
+
+ fn as_bytes_with_nul(self) -> Self::Result {
+ self.as_cstr().to_bytes_with_nul()
+ }
+}
+
+unsafe impl BnStrCompatible for BnString {
+ type Result = Self;
+
+ fn as_bytes_with_nul(self) -> Self::Result {
+ self
+ }
+}
+
+unsafe impl<'a> BnStrCompatible for &'a CStr {
+ type Result = &'a [u8];
+
+ fn as_bytes_with_nul(self) -> Self::Result {
+ self.to_bytes_with_nul()
+ }
+}
+
+unsafe impl BnStrCompatible for CString {
+ type Result = Vec<u8>;
+
+ fn as_bytes_with_nul(self) -> Self::Result {
+ self.into_bytes_with_nul()
+ }
+}
+
+unsafe impl<'a> BnStrCompatible for &'a str {
+ type Result = Vec<u8>;
+
+ fn as_bytes_with_nul(self) -> Self::Result {
+ let ret = CString::new(self).expect("can't pass strings with internal nul bytes to core!");
+ ret.into_bytes_with_nul()
+ }
+}
+
+unsafe impl BnStrCompatible for String {
+ type Result = Vec<u8>;
+
+ fn as_bytes_with_nul(self) -> Self::Result {
+ let ret = CString::new(self).expect("can't pass strings with internal nul bytes to core!");
+ ret.into_bytes_with_nul()
+ }
+}