LHASH: Fix documentation for doall-delete hazards
authorHugo Landau <hlandau@openssl.org>
Fri, 8 Dec 2023 10:14:27 +0000 (10:14 +0000)
committerTomas Mraz <tomas@openssl.org>
Fri, 15 Dec 2023 11:46:16 +0000 (12:46 +0100)
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tom Cosgrove <tom.cosgrove@arm.com>
Reviewed-by: Neil Horman <nhorman@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/23032)

(cherry picked from commit e91f21193c1b11de775e65b4e209a9fed67a41c1)

doc/man3/OPENSSL_LH_COMPFUNC.pod

index ba128404b30b06413603bede53bafdfb8cefd529..06408e0dd67da87107e4f80b706ba232a9fb284c 100644 (file)
@@ -157,15 +157,6 @@ For example:
  /* Then the hash table itself can be deallocated */
  lh_TYPE_free(hashtable);
 
-When doing this, be careful if you delete entries from the hash table
-in your callbacks: the table may decrease in size, moving the item
-that you are currently on down lower in the hash table - this could
-cause some entries to be skipped during the iteration.  The second
-best solution to this problem is to set hash-E<gt>down_load=0 before
-you start (which will stop the hash table ever decreasing in size).
-The best solution is probably to avoid deleting items from the hash
-table inside a "doall" callback!
-
 B<lh_I<TYPE>_doall_arg>() is the same as B<lh_I<TYPE>_doall>() except that
 I<func> will be called with I<arg> as the second argument and I<func>
 should be of type B<LHASH_DOALL_ARG_FN>(B<I<TYPE>>) (a callback prototype
@@ -187,6 +178,23 @@ that is provided by the caller):
  lh_TYPE_doall_arg(hashtable, LHASH_DOALL_ARG_FN(TYPE_print), BIO,
                    logging_bio);
 
+Note that it is by default B<not> safe to use B<lh_I<TYPE>_delete>() inside a
+callback passed to B<lh_I<TYPE>_doall>() or B<lh_I<TYPE>_doall_arg>(). The
+reason for this is that deleting an item from the hash table may result in the
+hash table being contracted to a smaller size and rehashed.
+B<lh_I<TYPE>_doall>() and B<lh_I<TYPE>_doall_arg>() are unsafe and will exhibit
+undefined behaviour under these conditions, as these functions assume the hash
+table size and bucket pointers do not change during the call.
+
+If it is desired to use B<lh_I<TYPE>_doall>() or B<lh_I<TYPE>_doall_arg>() with
+B<lh_I<TYPE>_delete>(), it is essential that you call
+B<lh_I<TYPE>_set_down_load>() with a I<down_load> argument of 0 first. This
+disables hash table contraction and guarantees that it will be safe to delete
+items from a hash table during a call to B<lh_I<TYPE>_doall>() or
+B<lh_I<TYPE>_doall_arg>().
+
+It is never safe to call B<lh_I<TYPE>_insert>() during a call to
+B<lh_I<TYPE>_doall>() or B<lh_I<TYPE>_doall_arg>().
 
 B<lh_I<TYPE>_error>() can be used to determine if an error occurred in the last
 operation.