@@ -32,6 +32,7 @@ typedef struct qd_hash_item_t {
32
32
void * val ;
33
33
const void * val_const ;
34
34
} v ;
35
+ qd_hash_handle_t * handle ;
35
36
} qd_hash_item_t ;
36
37
37
38
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)
105
106
//remove the given item from the given bucket of the given hash
106
107
//return the key if non-null key pointer given, otherwise, free the memory
107
108
static void qd_hash_internal_remove_item (qd_hash_t * h , bucket_t * bucket , qd_hash_item_t * item , unsigned char * * key ) {
108
- if (key )
109
+ if (key ) {
109
110
* key = item -> key ;
110
- else
111
+ }
112
+ else {
111
113
free (item -> key );
114
+ item -> key = 0 ;
115
+ }
112
116
DEQ_REMOVE (bucket -> items , item );
117
+
118
+ //
119
+ // We are going to free this item, so we will set the
120
+ // item pointer on the hash_handle to zero so nobody with
121
+ // access to the hash_handle can ever try to get to this freed item.
122
+ // The item and the hash_handle can be freed independent of one another.
123
+ //
124
+ if (item -> handle ) {
125
+ item -> handle -> item = 0 ;
126
+ }
113
127
free_qd_hash_item_t (item );
114
128
h -> size -- ;
115
129
}
@@ -151,14 +165,20 @@ static qd_hash_item_t *qd_hash_internal_insert(qd_hash_t *h, bucket_t *bucket, u
151
165
152
166
if (item ) {
153
167
* exists = 1 ;
154
- if (handle )
168
+ if (handle ) {
169
+ //
170
+ // If the item already exists, we return the item and also return a zero hash handle.
171
+ // This means that there is ever only one hash handle for an item.
172
+ //
155
173
* handle = 0 ;
174
+ }
156
175
return item ;
157
176
}
158
177
159
178
item = new_qd_hash_item_t ();
160
179
if (!item )
161
180
return 0 ;
181
+ item -> handle = 0 ;
162
182
163
183
DEQ_ITEM_INIT (item );
164
184
item -> key = key ;
@@ -174,6 +194,15 @@ static qd_hash_item_t *qd_hash_internal_insert(qd_hash_t *h, bucket_t *bucket, u
174
194
* handle = new_qd_hash_handle_t ();
175
195
(* handle )-> bucket = bucket ;
176
196
(* handle )-> item = item ;
197
+
198
+ //
199
+ // There is ever only one hash_handle that points to an item.
200
+ // We will store that hash_handle in the item itself because
201
+ // when the item is freed, the item pointer on its associated hash_handle will
202
+ // be set to zero so that nobody can try to access the item via the handle after
203
+ // the item is freed.
204
+ //
205
+ item -> handle = * handle ;
177
206
}
178
207
179
208
return item ;
@@ -292,7 +321,7 @@ void qd_hash_retrieve_prefix(qd_hash_t *h, qd_iterator_t *iter, void **val)
292
321
293
322
uint32_t hash = 0 ;
294
323
295
- qd_hash_item_t * item ;
324
+ qd_hash_item_t * item = 0 ;
296
325
while (qd_iterator_next_segment (iter , & hash )) {
297
326
item = qd_hash_internal_retrieve_with_hash (h , hash , iter );
298
327
if (item )
@@ -315,8 +344,7 @@ void qd_hash_retrieve_prefix_const(qd_hash_t *h, qd_iterator_t *iter, const void
315
344
316
345
uint32_t hash = 0 ;
317
346
318
- qd_hash_item_t * item ;
319
-
347
+ qd_hash_item_t * item = 0 ;
320
348
while (qd_iterator_next_segment (iter , & hash )) {
321
349
item = qd_hash_internal_retrieve_with_hash (h , hash , iter );
322
350
if (item )
@@ -425,7 +453,7 @@ void qd_hash_handle_free(qd_hash_handle_t *handle)
425
453
426
454
const unsigned char * qd_hash_key_by_handle (const qd_hash_handle_t * handle )
427
455
{
428
- if (handle )
456
+ if (handle && handle -> item )
429
457
return handle -> item -> key ;
430
458
return 0 ;
431
459
}
@@ -447,7 +475,11 @@ qd_error_t qd_hash_remove_by_handle(qd_hash_t *h, qd_hash_handle_t *handle)
447
475
448
476
qd_error_t qd_hash_remove_by_handle2 (qd_hash_t * h , qd_hash_handle_t * handle , unsigned char * * key )
449
477
{
450
- if (!handle )
478
+ //
479
+ // If the handle is not supplied or if the supplied handle has no item, we don't want to proceed
480
+ // removing the item by handle.
481
+ //
482
+ if (!handle || !handle -> item )
451
483
return QD_ERROR_NOT_FOUND ;
452
484
qd_hash_internal_remove_item (h , handle -> bucket , handle -> item , key );
453
485
return QD_ERROR_NONE ;
0 commit comments