commit 1d65de2b8005afe81e06ac65fd55987f173f776b
parent 2d957ad753aeb461e71212950a84a4474fa40694
Author: William Casarin <jb55@jb55.com>
Date: Fri, 9 Feb 2024 15:10:51 -0800
filter: fix double free issues via ndb_filter_clone
Signed-off-by: William Casarin <jb55@jb55.com>
Diffstat:
M | src/filter.rs | | | 137 | +++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------- |
M | src/ndb.rs | | | 11 | ++++------- |
2 files changed, 96 insertions(+), 52 deletions(-)
diff --git a/src/filter.rs b/src/filter.rs
@@ -3,22 +3,46 @@ use crate::Note;
use std::ffi::CString;
use std::os::raw::c_char;
use std::ptr::null_mut;
+use tracing::debug;
-#[derive(Debug, Clone)]
+#[derive(Debug)]
+pub struct FilterBuilder {
+ pub data: bindings::ndb_filter,
+}
+
+#[derive(Debug)]
pub struct Filter {
pub data: bindings::ndb_filter,
}
+impl Clone for Filter {
+ fn clone(&self) -> Self {
+ let mut new_filter: bindings::ndb_filter = Default::default();
+ unsafe {
+ bindings::ndb_filter_clone(
+ new_filter.as_mut_ptr(),
+ self.as_ptr() as *mut bindings::ndb_filter,
+ );
+ };
+ Filter { data: new_filter }
+ }
+}
+
impl bindings::ndb_filter {
fn as_ptr(&self) -> *const bindings::ndb_filter {
self as *const bindings::ndb_filter
}
+
+ fn as_mut_ptr(&mut self) -> *mut bindings::ndb_filter {
+ self as *mut bindings::ndb_filter
+ }
}
-impl Filter {
- pub fn new() -> Filter {
+impl Default for bindings::ndb_filter {
+ fn default() -> Self {
let null = null_mut();
let mut filter_data = bindings::ndb_filter {
+ finalized: 0,
elem_buf: bindings::cursor {
start: null,
p: null,
@@ -30,96 +54,119 @@ impl Filter {
end: null,
},
num_elements: 0,
- current: null_mut(),
- elements: [
- null_mut(),
- null_mut(),
- null_mut(),
- null_mut(),
- null_mut(),
- null_mut(),
- null_mut(),
- ],
+ current: -1,
+ elements: [0, 0, 0, 0, 0, 0, 0],
};
unsafe {
- bindings::ndb_filter_init(&mut filter_data as *mut bindings::ndb_filter);
+ bindings::ndb_filter_init(filter_data.as_mut_ptr());
};
- Self { data: filter_data }
+ filter_data
+ }
+}
+
+impl Filter {
+ pub fn new() -> FilterBuilder {
+ FilterBuilder {
+ data: Default::default(),
+ }
+ }
+
+ pub fn matches(&self, note: &Note) -> bool {
+ unsafe {
+ bindings::ndb_filter_matches(self.as_ptr() as *mut bindings::ndb_filter, note.as_ptr())
+ != 0
+ }
}
pub fn as_ptr(&self) -> *const bindings::ndb_filter {
return self.data.as_ptr();
}
- pub fn as_mut_ptr(&self) -> *mut bindings::ndb_filter {
- return self.data.as_ptr() as *mut bindings::ndb_filter;
+ pub fn as_mut_ptr(&mut self) -> *mut bindings::ndb_filter {
+ return self.data.as_mut_ptr() as *mut bindings::ndb_filter;
}
+}
- fn add_int_element(&self, i: u64) {
+impl FilterBuilder {
+ pub fn new() -> FilterBuilder {
+ Self {
+ data: Default::default(),
+ }
+ }
+
+ pub fn as_ptr(&self) -> *const bindings::ndb_filter {
+ return self.data.as_ptr();
+ }
+
+ pub fn as_mut_ptr(&mut self) -> *mut bindings::ndb_filter {
+ return self.data.as_mut_ptr();
+ }
+
+ fn add_int_element(&mut self, i: u64) {
unsafe { bindings::ndb_filter_add_int_element(self.as_mut_ptr(), i) };
}
- fn add_str_element(&self, s: &str) {
+ fn add_str_element(&mut self, s: &str) {
let c_str = CString::new(s).expect("string to cstring conversion failed");
unsafe {
bindings::ndb_filter_add_str_element(self.as_mut_ptr(), c_str.as_ptr());
};
}
- fn add_id_element(&self, id: &[u8; 32]) {
+ fn add_id_element(&mut self, id: &[u8; 32]) {
let ptr: *const ::std::os::raw::c_uchar = id.as_ptr() as *const ::std::os::raw::c_uchar;
unsafe {
bindings::ndb_filter_add_id_element(self.as_mut_ptr(), ptr);
};
}
- fn start_field(&self, field: bindings::ndb_filter_fieldtype) {
+ fn start_field(&mut self, field: bindings::ndb_filter_fieldtype) {
unsafe { bindings::ndb_filter_start_field(self.as_mut_ptr(), field) };
}
- fn start_tags_field(&self, tag: char) {
+ fn start_tags_field(&mut self, tag: char) {
unsafe { bindings::ndb_filter_start_tag_field(self.as_mut_ptr(), tag as i8) };
}
- fn start_kinds_field(&self) {
+ fn start_kinds_field(&mut self) {
self.start_field(bindings::ndb_filter_fieldtype_NDB_FILTER_KINDS);
}
- fn start_authors_field(&self) {
+ fn start_authors_field(&mut self) {
self.start_field(bindings::ndb_filter_fieldtype_NDB_FILTER_AUTHORS);
}
- fn start_since_field(&self) {
+ fn start_since_field(&mut self) {
self.start_field(bindings::ndb_filter_fieldtype_NDB_FILTER_SINCE);
}
- fn start_limit_field(&self) {
+ fn start_limit_field(&mut self) {
self.start_field(bindings::ndb_filter_fieldtype_NDB_FILTER_LIMIT);
}
- fn start_ids_field(&self) {
+ fn start_ids_field(&mut self) {
self.start_field(bindings::ndb_filter_fieldtype_NDB_FILTER_IDS);
}
- fn start_events_field(&self) {
+ fn start_events_field(&mut self) {
self.start_tags_field('e');
}
- fn start_pubkeys_field(&self) {
+ fn start_pubkeys_field(&mut self) {
self.start_tags_field('p');
}
- fn start_tag_field(&self, tag: char) {
+ fn start_tag_field(&mut self, tag: char) {
unsafe { bindings::ndb_filter_start_tag_field(self.as_mut_ptr(), tag as u8 as c_char) };
}
- fn end_field(&self) {
+ fn end_field(&mut self) {
unsafe { bindings::ndb_filter_end_field(self.as_mut_ptr()) }
}
- pub fn events(&mut self, events: Vec<[u8; 32]>) -> &mut Filter {
+ pub fn events(&mut self, events: Vec<[u8; 32]>) -> &mut Self {
self.start_tag_field('e');
for ref id in events {
self.add_id_element(id);
@@ -128,7 +175,7 @@ impl Filter {
self
}
- pub fn ids(&mut self, ids: Vec<[u8; 32]>) -> &mut Filter {
+ pub fn ids(&mut self, ids: Vec<[u8; 32]>) -> &mut Self {
self.start_ids_field();
for ref id in ids {
self.add_id_element(id);
@@ -137,7 +184,7 @@ impl Filter {
self
}
- pub fn pubkeys(&mut self, pubkeys: Vec<[u8; 32]>) -> &mut Filter {
+ pub fn pubkeys(&mut self, pubkeys: Vec<[u8; 32]>) -> &mut Self {
self.start_tag_field('p');
for ref pk in pubkeys {
self.add_id_element(pk);
@@ -146,7 +193,7 @@ impl Filter {
self
}
- pub fn authors(&mut self, authors: Vec<[u8; 32]>) -> &mut Filter {
+ pub fn authors(&mut self, authors: Vec<[u8; 32]>) -> &mut Self {
self.start_authors_field();
for author in authors {
self.add_id_element(&author);
@@ -155,7 +202,7 @@ impl Filter {
self
}
- pub fn kinds(&mut self, kinds: Vec<u64>) -> &mut Filter {
+ pub fn kinds(&mut self, kinds: Vec<u64>) -> &mut Self {
self.start_kinds_field();
for kind in kinds {
self.add_int_element(kind);
@@ -164,7 +211,7 @@ impl Filter {
self
}
- pub fn pubkey(&mut self, pubkeys: Vec<[u8; 32]>) -> &mut Filter {
+ pub fn pubkey(&mut self, pubkeys: Vec<[u8; 32]>) -> &mut Self {
self.start_pubkeys_field();
for ref pubkey in pubkeys {
self.add_id_element(pubkey);
@@ -173,7 +220,7 @@ impl Filter {
self
}
- pub fn tags(&mut self, tags: Vec<String>, tag: char) -> &mut Filter {
+ pub fn tags(&mut self, tags: Vec<String>, tag: char) -> &mut Self {
self.start_tag_field(tag);
for tag in tags {
self.add_str_element(&tag);
@@ -182,31 +229,31 @@ impl Filter {
self
}
- pub fn since(&mut self, since: u64) -> &mut Filter {
+ pub fn since(&mut self, since: u64) -> &mut Self {
self.start_since_field();
self.add_int_element(since);
self.end_field();
self
}
- pub fn limit(&mut self, limit: u64) -> &mut Filter {
+ pub fn limit(&mut self, limit: u64) -> &mut Self {
self.start_since_field();
self.add_int_element(limit);
self.end_field();
self
}
- pub fn matches(&self, note: &Note) -> bool {
- unsafe { bindings::ndb_filter_matches(self.as_mut_ptr(), note.as_ptr()) != 0 }
+ pub fn build(&mut self) -> Filter {
+ unsafe {
+ bindings::ndb_filter_end(self.as_mut_ptr());
+ };
+ Filter { data: self.data }
}
}
-/*
-// This is unsafe.. but we still need a way to free the memory on these
impl Drop for Filter {
fn drop(&mut self) {
debug!("dropping filter {:?}", self);
unsafe { bindings::ndb_filter_destroy(self.as_mut_ptr()) };
}
}
-*/
diff --git a/src/ndb.rs b/src/ndb.rs
@@ -328,10 +328,9 @@ mod tests {
{
let ndb = Ndb::new(db, &Config::new()).expect("ndb");
- let mut filter = Filter::new();
- filter.kinds(vec![1]);
-
+ let filter = Filter::new().kinds(vec![1]).build();
let filters = vec![filter];
+
let sub = ndb.subscribe(filters.clone()).expect("sub_id");
let waiter = ndb.wait_for_notes(&sub, 1);
ndb.process_event(r#"["EVENT","b",{"id": "702555e52e82cc24ad517ba78c21879f6e47a7c0692b9b20df147916ae8731a3","pubkey": "32bf915904bfde2d136ba45dde32c88f4aca863783999faea2e847a8fafd2f15","created_at": 1702675561,"kind": 1,"tags": [],"content": "hello, world","sig": "2275c5f5417abfd644b7bc74f0388d70feb5d08b6f90fa18655dda5c95d013bfbc5258ea77c05b7e40e0ee51d8a2efa931dc7a0ec1db4c0a94519762c6625675"}]"#).expect("process ok");
@@ -355,8 +354,7 @@ mod tests {
{
let ndb = Ndb::new(db, &Config::new()).expect("ndb");
- let mut filter = Filter::new();
- filter.kinds(vec![1]);
+ let filter = Filter::new().kinds(vec![1]).build();
let sub = ndb.subscribe(vec![filter]).expect("sub_id");
let waiter = ndb.wait_for_notes(&sub, 1);
@@ -374,8 +372,7 @@ mod tests {
{
let ndb = Ndb::new(db, &Config::new()).expect("ndb");
- let mut filter = Filter::new();
- filter.kinds(vec![1]);
+ let filter = Filter::new().kinds(vec![1]).build();
let sub = ndb.subscribe(vec![filter]).expect("sub_id");
ndb.process_event(r#"["EVENT","b",{"id": "702555e52e82cc24ad517ba78c21879f6e47a7c0692b9b20df147916ae8731a3","pubkey": "32bf915904bfde2d136ba45dde32c88f4aca863783999faea2e847a8fafd2f15","created_at": 1702675561,"kind": 1,"tags": [],"content": "hello, world","sig": "2275c5f5417abfd644b7bc74f0388d70feb5d08b6f90fa18655dda5c95d013bfbc5258ea77c05b7e40e0ee51d8a2efa931dc7a0ec1db4c0a94519762c6625675"}]"#).expect("process ok");