Skip to content

Commit 1b552d7

Browse files
committed
[Rust] Fix BinaryViewExt::address_comments leaking and refactor
1 parent c9b43e1 commit 1b552d7

File tree

1 file changed

+47
-15
lines changed

1 file changed

+47
-15
lines changed

rust/src/binary_view.rs

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1686,22 +1686,27 @@ pub trait BinaryViewExt: BinaryViewBase {
16861686
unsafe { BNRemoveUserDataTag(self.as_ref().handle, addr, tag.handle) }
16871687
}
16881688

1689-
fn address_comments(&self) -> BTreeMap<u64, String> {
1690-
let mut comment_count = 0;
1691-
let mut result = BTreeMap::new();
1692-
let addresses;
1693-
unsafe {
1694-
let addresses_raw =
1695-
BNGetGlobalCommentedAddresses(self.as_ref().handle, &mut comment_count);
1696-
addresses = std::slice::from_raw_parts(addresses_raw, comment_count);
1697-
}
1689+
/// Retrieves a list of comment addresses, the comments themselves can then be queried with
1690+
/// the function [`BinaryViewExt::comment_at`].
1691+
///
1692+
/// If you would rather retrieve the contents of **all** comments at once you can do so with
1693+
/// the helper function [`BinaryViewExt::comments`].
1694+
fn comment_references(&self) -> Array<CommentReference> {
1695+
let mut count = 0;
1696+
let addresses_raw =
1697+
unsafe { BNGetGlobalCommentedAddresses(self.as_ref().handle, &mut count) };
1698+
unsafe { Array::new(addresses_raw, count, ()) }
1699+
}
16981700

1699-
for address in addresses {
1700-
if let Some(comment) = self.comment_at(*address) {
1701-
result.insert(*address, comment);
1702-
}
1703-
}
1704-
result
1701+
/// Retrieves a map of comment addresses to their contents.
1702+
///
1703+
/// This is a helper function that eagerly reads the contents of all comments within the
1704+
/// view, use [`BinaryViewExt::comment_references`] instead if you do not wish to read all the comments.
1705+
fn comments(&self) -> BTreeMap<u64, String> {
1706+
self.comment_references()
1707+
.iter()
1708+
.filter_map(|cmt_ref| Some((cmt_ref.start, self.comment_at(cmt_ref.start)?)))
1709+
.collect()
17051710
}
17061711

17071712
fn comment_at(&self, addr: u64) -> Option<String> {
@@ -2710,6 +2715,33 @@ where
27102715
}
27112716
}
27122717

2718+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2719+
pub struct CommentReference {
2720+
pub start: u64,
2721+
}
2722+
2723+
impl From<u64> for CommentReference {
2724+
fn from(start: u64) -> Self {
2725+
Self { start }
2726+
}
2727+
}
2728+
2729+
impl CoreArrayProvider for CommentReference {
2730+
type Raw = u64;
2731+
type Context = ();
2732+
type Wrapped<'a> = Self;
2733+
}
2734+
2735+
unsafe impl CoreArrayProviderInner for CommentReference {
2736+
unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
2737+
BNFreeAddressList(raw)
2738+
}
2739+
2740+
unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
2741+
Self::from(*raw)
2742+
}
2743+
}
2744+
27132745
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
27142746
pub struct StringReference {
27152747
pub ty: StringType,

0 commit comments

Comments
 (0)