commit f47d74f471b69da70d9c10b6b2856a3d051e3720
parent f243083f9231139da7708d0e1359a98e18e0e5bb
Author: William Casarin <jb55@jb55.com>
Date: Fri, 9 Feb 2024 14:07:43 -0800
filter: add ndb_filter_clone
Clone filters when moving them into subscriptions. This will allow us to
fix the double free issue on the rust side.
Signed-off-by: William Casarin <jb55@jb55.com>
Diffstat:
2 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/src/nostrdb.c b/src/nostrdb.c
@@ -514,6 +514,35 @@ static inline int ndb_filter_elem_is_ptr(struct ndb_filter_field *field) {
return field->elem_type == NDB_ELEMENT_STRING || field->elem_type == NDB_ELEMENT_ID;
}
+// Copy the filter
+int ndb_filter_clone(struct ndb_filter *dst, struct ndb_filter *src)
+{
+ size_t src_size, elem_size, data_size;
+
+ elem_size = src->elem_buf.end - src->elem_buf.start;
+ data_size = src->data_buf.end - src->data_buf.start;
+ src_size = data_size + elem_size;
+
+ // let's only allow finalized filters to be cloned
+ if (!src || !src->finalized)
+ return 0;
+
+ dst->elem_buf.start = malloc(src_size);
+ dst->elem_buf.end = dst->elem_buf.start + elem_size;
+ dst->elem_buf.p = dst->elem_buf.end;
+
+ dst->data_buf.start = dst->elem_buf.start + elem_size;
+ dst->data_buf.end = dst->data_buf.start + data_size;
+ dst->data_buf.p = dst->data_buf.end;
+
+ if (dst->elem_buf.start == NULL)
+ return 0;
+
+ memcpy(dst->elem_buf.start, src->elem_buf.start, src_size);
+
+ return 1;
+}
+
// "Finalize" the filter. This resizes the allocated heap buffers so that they
// are as small as possible. This also prevents new fields from being added
int ndb_filter_end(struct ndb_filter *filter)
@@ -1127,7 +1156,7 @@ static int ndb_filter_group_add(struct ndb_filter_group *group,
if (group->num_filters + 1 > MAX_FILTERS)
return 0;
- memcpy(&group->filters[group->num_filters++], filter, sizeof(*filter));
+ ndb_filter_clone(&group->filters[group->num_filters++], filter);
return 1;
}
diff --git a/src/nostrdb.h b/src/nostrdb.h
@@ -484,6 +484,7 @@ struct ndb_filter_elements *ndb_filter_current_element(struct ndb_filter *);
int ndb_filter_start_field(struct ndb_filter *, enum ndb_filter_fieldtype);
int ndb_filter_start_tag_field(struct ndb_filter *, char tag);
int ndb_filter_matches(struct ndb_filter *, struct ndb_note *);
+int ndb_filter_clone(struct ndb_filter *dst, struct ndb_filter *src);
int ndb_filter_end(struct ndb_filter *);
void ndb_filter_end_field(struct ndb_filter *);
void ndb_filter_destroy(struct ndb_filter *);