You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by gm...@apache.org on 2021/03/18 00:59:12 UTC
[qpid-dispatch] branch master updated: DISPATCH-1660: Introduced a
hash_handle on the item so we can set the item->hash_handle->item to zero
when the item is freed. This ensures that the hash_handle will never be
able to reach the freed item. This closes #1075.
This is an automated email from the ASF dual-hosted git repository.
gmurthy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/qpid-dispatch.git
The following commit(s) were added to refs/heads/master by this push:
new 1625d83 DISPATCH-1660: Introduced a hash_handle on the item so we can set the item->hash_handle->item to zero when the item is freed. This ensures that the hash_handle will never be able to reach the freed item. This closes #1075.
1625d83 is described below
commit 1625d831354384c085d288dfaf9a0d116c626d3a
Author: Ganesh Murthy <gm...@apache.org>
AuthorDate: Tue Mar 16 20:49:20 2021 -0400
DISPATCH-1660: Introduced a hash_handle on the item so we can set the item->hash_handle->item to zero when the item is freed. This ensures that the hash_handle will never be able to reach the freed item. This closes #1075.
---
src/hash.c | 48 ++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 40 insertions(+), 8 deletions(-)
diff --git a/src/hash.c b/src/hash.c
index 35293e6..aa1a3d4 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -32,6 +32,7 @@ typedef struct qd_hash_item_t {
void *val;
const void *val_const;
} v;
+ qd_hash_handle_t *handle;
} qd_hash_item_t;
ALLOC_DECLARE(qd_hash_item_t);
@@ -105,11 +106,24 @@ qd_hash_t *qd_hash(int bucket_exponent, int batch_size, int value_is_const)
//remove the given item from the given bucket of the given hash
//return the key if non-null key pointer given, otherwise, free the memory
static void qd_hash_internal_remove_item(qd_hash_t *h, bucket_t *bucket, qd_hash_item_t *item, unsigned char **key) {
- if (key)
+ if (key) {
*key = item->key;
- else
+ }
+ else {
free(item->key);
+ item->key = 0;
+ }
DEQ_REMOVE(bucket->items, item);
+
+ //
+ // We are going to free this item, so we will set the
+ // item pointer on the hash_handle to zero so nobody with
+ // access to the hash_handle can ever try to get to this freed item.
+ // The item and the hash_handle can be freed independent of one another.
+ //
+ if (item->handle) {
+ item->handle->item = 0;
+ }
free_qd_hash_item_t(item);
h->size--;
}
@@ -151,14 +165,20 @@ static qd_hash_item_t *qd_hash_internal_insert(qd_hash_t *h, bucket_t *bucket, u
if (item) {
*exists = 1;
- if (handle)
+ if (handle) {
+ //
+ // If the item already exists, we return the item and also return a zero hash handle.
+ // This means that there is ever only one hash handle for an item.
+ //
*handle = 0;
+ }
return item;
}
item = new_qd_hash_item_t();
if (!item)
return 0;
+ item->handle = 0;
DEQ_ITEM_INIT(item);
item->key = key;
@@ -174,6 +194,15 @@ static qd_hash_item_t *qd_hash_internal_insert(qd_hash_t *h, bucket_t *bucket, u
*handle = new_qd_hash_handle_t();
(*handle)->bucket = bucket;
(*handle)->item = item;
+
+ //
+ // There is ever only one hash_handle that points to an item.
+ // We will store that hash_handle in the item itself because
+ // when the item is freed, the item pointer on its associated hash_handle will
+ // be set to zero so that nobody can try to access the item via the handle after
+ // the item is freed.
+ //
+ item->handle = *handle;
}
return item;
@@ -292,7 +321,7 @@ void qd_hash_retrieve_prefix(qd_hash_t *h, qd_iterator_t *iter, void **val)
uint32_t hash = 0;
- qd_hash_item_t *item;
+ qd_hash_item_t *item = 0;
while (qd_iterator_next_segment(iter, &hash)) {
item = qd_hash_internal_retrieve_with_hash(h, hash, iter);
if (item)
@@ -315,8 +344,7 @@ void qd_hash_retrieve_prefix_const(qd_hash_t *h, qd_iterator_t *iter, const void
uint32_t hash = 0;
- qd_hash_item_t *item;
-
+ qd_hash_item_t *item = 0;
while (qd_iterator_next_segment(iter, &hash)) {
item = qd_hash_internal_retrieve_with_hash(h, hash, iter);
if (item)
@@ -425,7 +453,7 @@ void qd_hash_handle_free(qd_hash_handle_t *handle)
const unsigned char *qd_hash_key_by_handle(const qd_hash_handle_t *handle)
{
- if (handle)
+ if (handle && handle->item)
return handle->item->key;
return 0;
}
@@ -447,7 +475,11 @@ qd_error_t qd_hash_remove_by_handle(qd_hash_t *h, qd_hash_handle_t *handle)
qd_error_t qd_hash_remove_by_handle2(qd_hash_t *h, qd_hash_handle_t *handle, unsigned char **key)
{
- if (!handle)
+ //
+ // If the handle is not supplied or if the supplied handle has no item, we don't want to proceed
+ // removing the item by handle.
+ //
+ if (!handle || !handle->item)
return QD_ERROR_NOT_FOUND;
qd_hash_internal_remove_item(h, handle->bucket, handle->item, key);
return QD_ERROR_NONE;
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org