| 
									
										
										
										
											2016-05-18 02:52:22 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2018-05-01 20:34:30 +08:00
										 |  |  |  * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-12-06 20:44:07 +08:00
										 |  |  |  * Licensed under the Apache License 2.0 (the "License").  You may not use | 
					
						
							| 
									
										
										
										
											2016-05-18 02:52:22 +08:00
										 |  |  |  * this file except in compliance with the License.  You can obtain a copy | 
					
						
							|  |  |  |  * in the file LICENSE in the source distribution or at | 
					
						
							|  |  |  |  * https://www.openssl.org/source/license.html
 | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							| 
									
										
										
										
											1999-04-24 06:13:45 +08:00
										 |  |  | #include <openssl/crypto.h>
 | 
					
						
							|  |  |  | #include <openssl/lhash.h>
 | 
					
						
							| 
									
										
										
										
											2018-04-27 02:02:24 +08:00
										 |  |  | #include <openssl/err.h>
 | 
					
						
							| 
									
										
										
										
											2018-09-04 05:35:45 +08:00
										 |  |  | #include "internal/ctype.h"
 | 
					
						
							|  |  |  | #include "internal/lhash.h"
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | #include "lhash_lcl.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-18 21:07:57 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * A hashing implementation that appears to be based on the linear hashing | 
					
						
							|  |  |  |  * alogrithm: | 
					
						
							|  |  |  |  * https://en.wikipedia.org/wiki/Linear_hashing
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Litwin, Witold (1980), "Linear hashing: A new tool for file and table | 
					
						
							| 
									
										
										
										
											2017-11-07 14:59:20 +08:00
										 |  |  |  * addressing", Proc. 6th Conference on Very Large Databases: 212-223 | 
					
						
							| 
									
										
										
										
											2017-10-18 21:07:57 +08:00
										 |  |  |  * http://hackthology.com/pdfs/Litwin-1980-Linear_Hashing.pdf
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * From the wikipedia article "Linear hashing is used in the BDB Berkeley | 
					
						
							|  |  |  |  * database system, which in turn is used by many software systems such as | 
					
						
							|  |  |  |  * OpenLDAP, using a C implementation derived from the CACM article and first | 
					
						
							|  |  |  |  * published on the Usenet in 1988 by Esmond Pitt." | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The CACM paper is available here: | 
					
						
							|  |  |  |  * https://pdfs.semanticscholar.org/ff4d/1c5deca6269cc316bfd952172284dbf610ee.pdf
 | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | #undef MIN_NODES
 | 
					
						
							|  |  |  | #define MIN_NODES       16
 | 
					
						
							|  |  |  | #define UP_LOAD         (2*LH_LOAD_MULT) /* load times 256 (default 2) */
 | 
					
						
							|  |  |  | #define DOWN_LOAD       (LH_LOAD_MULT) /* load times 256 (default 1) */
 | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-16 18:00:38 +08:00
										 |  |  | static int expand(OPENSSL_LHASH *lh); | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | static void contract(OPENSSL_LHASH *lh); | 
					
						
							|  |  |  | static OPENSSL_LH_NODE **getrn(OPENSSL_LHASH *lh, const void *data, unsigned long *rhash); | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | OPENSSL_LHASH *OPENSSL_LH_new(OPENSSL_LH_HASHFUNC h, OPENSSL_LH_COMPFUNC c) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  |     OPENSSL_LHASH *ret; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-27 02:02:24 +08:00
										 |  |  |     if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * Do not set the error code, because the ERR code uses LHASH | 
					
						
							|  |  |  |          * and we want to avoid possible endless error loop. | 
					
						
							|  |  |  |          * CRYPTOerr(CRYPTO_F_OPENSSL_LH_NEW, ERR_R_MALLOC_FAILURE); | 
					
						
							|  |  |  |          */ | 
					
						
							| 
									
										
										
										
											2017-06-07 23:23:37 +08:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2018-04-27 02:02:24 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-09-03 21:15:26 +08:00
										 |  |  |     if ((ret->b = OPENSSL_zalloc(sizeof(*ret->b) * MIN_NODES)) == NULL) | 
					
						
							| 
									
										
										
										
											2017-06-07 23:23:37 +08:00
										 |  |  |         goto err; | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  |     ret->comp = ((c == NULL) ? (OPENSSL_LH_COMPFUNC)strcmp : c); | 
					
						
							|  |  |  |     ret->hash = ((h == NULL) ? (OPENSSL_LH_HASHFUNC)OPENSSL_LH_strhash : h); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     ret->num_nodes = MIN_NODES / 2; | 
					
						
							|  |  |  |     ret->num_alloc_nodes = MIN_NODES; | 
					
						
							|  |  |  |     ret->pmax = MIN_NODES / 2; | 
					
						
							|  |  |  |     ret->up_load = UP_LOAD; | 
					
						
							|  |  |  |     ret->down_load = DOWN_LOAD; | 
					
						
							| 
									
										
										
										
											2017-09-28 08:09:18 +08:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2015-09-03 21:15:26 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-07 23:23:37 +08:00
										 |  |  | err: | 
					
						
							|  |  |  |     OPENSSL_free(ret->b); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     OPENSSL_free(ret); | 
					
						
							| 
									
										
										
										
											2017-06-07 23:23:37 +08:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | void OPENSSL_LH_free(OPENSSL_LHASH *lh) | 
					
						
							| 
									
										
										
										
											2018-11-16 09:44:30 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     if (lh == NULL) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     OPENSSL_LH_flush(lh); | 
					
						
							|  |  |  |     OPENSSL_free(lh->b); | 
					
						
							|  |  |  |     OPENSSL_free(lh); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void OPENSSL_LH_flush(OPENSSL_LHASH *lh) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     unsigned int i; | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  |     OPENSSL_LH_NODE *n, *nn; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (lh == NULL) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < lh->num_nodes; i++) { | 
					
						
							|  |  |  |         n = lh->b[i]; | 
					
						
							|  |  |  |         while (n != NULL) { | 
					
						
							|  |  |  |             nn = n->next; | 
					
						
							|  |  |  |             OPENSSL_free(n); | 
					
						
							|  |  |  |             n = nn; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | void *OPENSSL_LH_insert(OPENSSL_LHASH *lh, void *data) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     unsigned long hash; | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  |     OPENSSL_LH_NODE *nn, **rn; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     void *ret; | 
					
						
							| 
									
										
										
										
											2016-07-01 08:55:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     lh->error = 0; | 
					
						
							| 
									
										
										
										
											2016-07-01 08:55:18 +08:00
										 |  |  |     if ((lh->up_load <= (lh->num_items * LH_LOAD_MULT / lh->num_nodes)) && !expand(lh)) | 
					
						
							|  |  |  |         return NULL;        /* 'lh->error++' already done in 'expand' */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     rn = getrn(lh, data, &hash); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (*rn == NULL) { | 
					
						
							| 
									
										
										
										
											2015-05-02 11:10:31 +08:00
										 |  |  |         if ((nn = OPENSSL_malloc(sizeof(*nn))) == NULL) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             lh->error++; | 
					
						
							| 
									
										
										
										
											2017-09-28 08:09:18 +08:00
										 |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |         nn->data = data; | 
					
						
							|  |  |  |         nn->next = NULL; | 
					
						
							|  |  |  |         nn->hash = hash; | 
					
						
							|  |  |  |         *rn = nn; | 
					
						
							|  |  |  |         ret = NULL; | 
					
						
							|  |  |  |         lh->num_insert++; | 
					
						
							|  |  |  |         lh->num_items++; | 
					
						
							|  |  |  |     } else {                    /* replace same key */ | 
					
						
							|  |  |  |         ret = (*rn)->data; | 
					
						
							|  |  |  |         (*rn)->data = data; | 
					
						
							|  |  |  |         lh->num_replace++; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-09-28 08:09:18 +08:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | void *OPENSSL_LH_delete(OPENSSL_LHASH *lh, const void *data) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     unsigned long hash; | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  |     OPENSSL_LH_NODE *nn, **rn; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     void *ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     lh->error = 0; | 
					
						
							|  |  |  |     rn = getrn(lh, data, &hash); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (*rn == NULL) { | 
					
						
							|  |  |  |         lh->num_no_delete++; | 
					
						
							| 
									
										
										
										
											2017-09-28 08:09:18 +08:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         nn = *rn; | 
					
						
							|  |  |  |         *rn = nn->next; | 
					
						
							|  |  |  |         ret = nn->data; | 
					
						
							|  |  |  |         OPENSSL_free(nn); | 
					
						
							|  |  |  |         lh->num_delete++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     lh->num_items--; | 
					
						
							|  |  |  |     if ((lh->num_nodes > MIN_NODES) && | 
					
						
							|  |  |  |         (lh->down_load >= (lh->num_items * LH_LOAD_MULT / lh->num_nodes))) | 
					
						
							|  |  |  |         contract(lh); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-28 08:09:18 +08:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | void *OPENSSL_LH_retrieve(OPENSSL_LHASH *lh, const void *data) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     unsigned long hash; | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  |     OPENSSL_LH_NODE **rn; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     void *ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-29 20:11:49 +08:00
										 |  |  |     tsan_store((TSAN_QUALIFIER int *)&lh->error, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     rn = getrn(lh, data, &hash); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (*rn == NULL) { | 
					
						
							| 
									
										
										
										
											2018-07-29 20:11:49 +08:00
										 |  |  |         tsan_counter(&lh->num_retrieve_miss); | 
					
						
							| 
									
										
										
										
											2017-06-07 23:23:37 +08:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         ret = (*rn)->data; | 
					
						
							| 
									
										
										
										
											2018-07-29 20:11:49 +08:00
										 |  |  |         tsan_counter(&lh->num_retrieve); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-07-29 20:11:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-07 23:23:37 +08:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | static void doall_util_fn(OPENSSL_LHASH *lh, int use_arg, | 
					
						
							|  |  |  |                           OPENSSL_LH_DOALL_FUNC func, | 
					
						
							|  |  |  |                           OPENSSL_LH_DOALL_FUNCARG func_arg, void *arg) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     int i; | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  |     OPENSSL_LH_NODE *a, *n; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (lh == NULL) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * reverse the order so we search from 'top to bottom' We were having | 
					
						
							|  |  |  |      * memory leaks otherwise | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     for (i = lh->num_nodes - 1; i >= 0; i--) { | 
					
						
							|  |  |  |         a = lh->b[i]; | 
					
						
							|  |  |  |         while (a != NULL) { | 
					
						
							|  |  |  |             n = a->next; | 
					
						
							|  |  |  |             if (use_arg) | 
					
						
							|  |  |  |                 func_arg(a->data, arg); | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 func(a->data); | 
					
						
							|  |  |  |             a = n; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | void OPENSSL_LH_doall(OPENSSL_LHASH *lh, OPENSSL_LH_DOALL_FUNC func) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  |     doall_util_fn(lh, 0, func, (OPENSSL_LH_DOALL_FUNCARG)0, NULL); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2001-01-09 08:02:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | void OPENSSL_LH_doall_arg(OPENSSL_LHASH *lh, OPENSSL_LH_DOALL_FUNCARG func, void *arg) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  |     doall_util_fn(lh, 1, (OPENSSL_LH_DOALL_FUNC)0, func, arg); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2001-01-09 08:02:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-16 18:00:38 +08:00
										 |  |  | static int expand(OPENSSL_LHASH *lh) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  |     OPENSSL_LH_NODE **n, **n1, **n2, *np; | 
					
						
							| 
									
										
										
										
											2017-10-18 21:07:57 +08:00
										 |  |  |     unsigned int p, pmax, nni, j; | 
					
						
							|  |  |  |     unsigned long hash; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     nni = lh->num_alloc_nodes; | 
					
						
							|  |  |  |     p = lh->p; | 
					
						
							|  |  |  |     pmax = lh->pmax; | 
					
						
							|  |  |  |     if (p + 1 >= pmax) { | 
					
						
							|  |  |  |         j = nni * 2; | 
					
						
							|  |  |  |         n = OPENSSL_realloc(lh->b, sizeof(OPENSSL_LH_NODE *) * j); | 
					
						
							|  |  |  |         if (n == NULL) { | 
					
						
							|  |  |  |             lh->error++; | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         lh->b = n; | 
					
						
							|  |  |  |         memset(n + nni, 0, sizeof(*n) * (j - nni)); | 
					
						
							|  |  |  |         lh->pmax = nni; | 
					
						
							|  |  |  |         lh->num_alloc_nodes = j; | 
					
						
							|  |  |  |         lh->num_expand_reallocs++; | 
					
						
							|  |  |  |         lh->p = 0; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         lh->p++; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     lh->num_nodes++; | 
					
						
							|  |  |  |     lh->num_expands++; | 
					
						
							|  |  |  |     n1 = &(lh->b[p]); | 
					
						
							| 
									
										
										
										
											2017-10-18 21:07:57 +08:00
										 |  |  |     n2 = &(lh->b[p + pmax]); | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  |     *n2 = NULL; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (np = *n1; np != NULL;) { | 
					
						
							|  |  |  |         hash = np->hash; | 
					
						
							|  |  |  |         if ((hash % nni) != p) { /* move it */ | 
					
						
							|  |  |  |             *n1 = (*n1)->next; | 
					
						
							|  |  |  |             np->next = *n2; | 
					
						
							|  |  |  |             *n2 = np; | 
					
						
							|  |  |  |         } else | 
					
						
							|  |  |  |             n1 = &((*n1)->next); | 
					
						
							|  |  |  |         np = *n1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-01 08:55:18 +08:00
										 |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | static void contract(OPENSSL_LHASH *lh) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  |     OPENSSL_LH_NODE **n, *n1, *np; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     np = lh->b[lh->p + lh->pmax - 1]; | 
					
						
							|  |  |  |     lh->b[lh->p + lh->pmax - 1] = NULL; /* 24/07-92 - eay - weird but :-( */ | 
					
						
							|  |  |  |     if (lh->p == 0) { | 
					
						
							| 
									
										
										
										
											2015-04-29 03:28:14 +08:00
										 |  |  |         n = OPENSSL_realloc(lh->b, | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  |                             (unsigned int)(sizeof(OPENSSL_LH_NODE *) * lh->pmax)); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if (n == NULL) { | 
					
						
							| 
									
										
										
										
											2015-04-29 03:28:14 +08:00
										 |  |  |             /* fputs("realloc error in lhash",stderr); */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             lh->error++; | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         lh->num_contract_reallocs++; | 
					
						
							|  |  |  |         lh->num_alloc_nodes /= 2; | 
					
						
							|  |  |  |         lh->pmax /= 2; | 
					
						
							|  |  |  |         lh->p = lh->pmax - 1; | 
					
						
							|  |  |  |         lh->b = n; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |         lh->p--; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     lh->num_nodes--; | 
					
						
							|  |  |  |     lh->num_contracts++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     n1 = lh->b[(int)lh->p]; | 
					
						
							|  |  |  |     if (n1 == NULL) | 
					
						
							|  |  |  |         lh->b[(int)lh->p] = np; | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         while (n1->next != NULL) | 
					
						
							|  |  |  |             n1 = n1->next; | 
					
						
							|  |  |  |         n1->next = np; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | static OPENSSL_LH_NODE **getrn(OPENSSL_LHASH *lh, | 
					
						
							|  |  |  |                                const void *data, unsigned long *rhash) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  |     OPENSSL_LH_NODE **ret, *n1; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     unsigned long hash, nn; | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  |     OPENSSL_LH_COMPFUNC cf; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     hash = (*(lh->hash)) (data); | 
					
						
							| 
									
										
										
										
											2018-07-29 20:11:49 +08:00
										 |  |  |     tsan_counter(&lh->num_hash_calls); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     *rhash = hash; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     nn = hash % lh->pmax; | 
					
						
							|  |  |  |     if (nn < lh->p) | 
					
						
							|  |  |  |         nn = hash % lh->num_alloc_nodes; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cf = lh->comp; | 
					
						
							|  |  |  |     ret = &(lh->b[(int)nn]); | 
					
						
							|  |  |  |     for (n1 = *ret; n1 != NULL; n1 = n1->next) { | 
					
						
							| 
									
										
										
										
											2018-07-29 20:11:49 +08:00
										 |  |  |         tsan_counter(&lh->num_hash_comps); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if (n1->hash != hash) { | 
					
						
							|  |  |  |             ret = &(n1->next); | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-07-29 20:11:49 +08:00
										 |  |  |         tsan_counter(&lh->num_comp_calls); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if (cf(n1->data, data) == 0) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         ret = &(n1->next); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-09-28 08:09:18 +08:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * The following hash seems to work very well on normal text strings no | 
					
						
							|  |  |  |  * collisions on /usr/dict/words and it distributes on %2^n quite well, not | 
					
						
							|  |  |  |  * as good as MD5, but still good. | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | unsigned long OPENSSL_LH_strhash(const char *c) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     unsigned long ret = 0; | 
					
						
							|  |  |  |     long n; | 
					
						
							|  |  |  |     unsigned long v; | 
					
						
							|  |  |  |     int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((c == NULL) || (*c == '\0')) | 
					
						
							| 
									
										
										
										
											2017-09-28 08:09:18 +08:00
										 |  |  |         return ret; | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     n = 0x100; | 
					
						
							|  |  |  |     while (*c) { | 
					
						
							|  |  |  |         v = n | (*c); | 
					
						
							|  |  |  |         n += 0x100; | 
					
						
							|  |  |  |         r = (int)((v >> 2) ^ v) & 0x0f; | 
					
						
							|  |  |  |         ret = (ret << r) | (ret >> (32 - r)); | 
					
						
							|  |  |  |         ret &= 0xFFFFFFFFL; | 
					
						
							|  |  |  |         ret ^= v * v; | 
					
						
							|  |  |  |         c++; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-09-28 08:09:18 +08:00
										 |  |  |     return (ret >> 16) ^ ret; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-04 05:35:45 +08:00
										 |  |  | unsigned long openssl_lh_strcasehash(const char *c) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     unsigned long ret = 0; | 
					
						
							|  |  |  |     long n; | 
					
						
							|  |  |  |     unsigned long v; | 
					
						
							|  |  |  |     int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (c == NULL || *c == '\0') | 
					
						
							|  |  |  |         return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (n = 0x100; *c != '\0'; n += 0x100) { | 
					
						
							|  |  |  |         v = n | ossl_tolower(*c); | 
					
						
							|  |  |  |         r = (int)((v >> 2) ^ v) & 0x0f; | 
					
						
							|  |  |  |         ret = (ret << r) | (ret >> (32 - r)); | 
					
						
							|  |  |  |         ret &= 0xFFFFFFFFL; | 
					
						
							|  |  |  |         ret ^= v * v; | 
					
						
							|  |  |  |         c++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return (ret >> 16) ^ ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | unsigned long OPENSSL_LH_num_items(const OPENSSL_LHASH *lh) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     return lh ? lh->num_items : 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-01-11 22:11:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | unsigned long OPENSSL_LH_get_down_load(const OPENSSL_LHASH *lh) | 
					
						
							| 
									
										
										
										
											2016-01-11 22:11:13 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     return lh->down_load; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | void OPENSSL_LH_set_down_load(OPENSSL_LHASH *lh, unsigned long down_load) | 
					
						
							| 
									
										
										
										
											2016-01-11 22:11:13 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     lh->down_load = down_load; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | int OPENSSL_LH_error(OPENSSL_LHASH *lh) | 
					
						
							| 
									
										
										
										
											2016-01-11 22:11:13 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     return lh->error; | 
					
						
							|  |  |  | } |