xref: /freebsd/crypto/openssl/fuzz/hashtable.c (revision e7be843b4a162e68651d3911f0357ed464915629)
1*e7be843bSPierre Pronchery /*
2*e7be843bSPierre Pronchery  * Copyright 2024 The OpenSSL Project Authors. All Rights Reserved.
3*e7be843bSPierre Pronchery  *
4*e7be843bSPierre Pronchery  * Licensed under the Apache License 2.0 (the "License");
5*e7be843bSPierre Pronchery  * you may not use this file except in compliance with the License.
6*e7be843bSPierre Pronchery  * You may obtain a copy of the License at
7*e7be843bSPierre Pronchery  * https://www.openssl.org/source/license.html
8*e7be843bSPierre Pronchery  * or in the file LICENSE in the source distribution.
9*e7be843bSPierre Pronchery  */
10*e7be843bSPierre Pronchery 
11*e7be843bSPierre Pronchery /*
12*e7be843bSPierre Pronchery  * Test hashtable operation.
13*e7be843bSPierre Pronchery  */
14*e7be843bSPierre Pronchery #include <limits.h>
15*e7be843bSPierre Pronchery #include <openssl/err.h>
16*e7be843bSPierre Pronchery #include <openssl/bio.h>
17*e7be843bSPierre Pronchery #include <internal/common.h>
18*e7be843bSPierre Pronchery #include <internal/hashtable.h>
19*e7be843bSPierre Pronchery #include "fuzzer.h"
20*e7be843bSPierre Pronchery 
21*e7be843bSPierre Pronchery /*
22*e7be843bSPierre Pronchery  * Make the key space very small here to make lookups
23*e7be843bSPierre Pronchery  * easy to predict for the purposes of validation
24*e7be843bSPierre Pronchery  * A two byte key gives us 65536 possible entries
25*e7be843bSPierre Pronchery  * so we can allocate a flat table to compare to
26*e7be843bSPierre Pronchery  */
27*e7be843bSPierre Pronchery HT_START_KEY_DEFN(fuzzer_key)
28*e7be843bSPierre Pronchery HT_DEF_KEY_FIELD(fuzzkey, uint16_t)
29*e7be843bSPierre Pronchery HT_END_KEY_DEFN(FUZZER_KEY)
30*e7be843bSPierre Pronchery 
31*e7be843bSPierre Pronchery #define FZ_FLAG_ALLOCATED (1 << 0)
32*e7be843bSPierre Pronchery typedef struct fuzzer_value_st {
33*e7be843bSPierre Pronchery     uint64_t flags;
34*e7be843bSPierre Pronchery     uint64_t value;
35*e7be843bSPierre Pronchery } FUZZER_VALUE;
36*e7be843bSPierre Pronchery 
37*e7be843bSPierre Pronchery IMPLEMENT_HT_VALUE_TYPE_FNS(FUZZER_VALUE, fz, static)
38*e7be843bSPierre Pronchery 
39*e7be843bSPierre Pronchery static size_t skipped_values = 0;
40*e7be843bSPierre Pronchery static size_t inserts = 0;
41*e7be843bSPierre Pronchery static size_t replacements = 0;
42*e7be843bSPierre Pronchery static size_t deletes = 0;
43*e7be843bSPierre Pronchery static size_t flushes = 0;
44*e7be843bSPierre Pronchery static size_t lookups = 0;
45*e7be843bSPierre Pronchery static size_t foreaches = 0;
46*e7be843bSPierre Pronchery static size_t filters = 0;
47*e7be843bSPierre Pronchery static int valfound;
48*e7be843bSPierre Pronchery 
49*e7be843bSPierre Pronchery static FUZZER_VALUE *prediction_table = NULL;
50*e7be843bSPierre Pronchery static HT *fuzzer_table = NULL;
51*e7be843bSPierre Pronchery 
52*e7be843bSPierre Pronchery /*
53*e7be843bSPierre Pronchery  * Operational values
54*e7be843bSPierre Pronchery  */
55*e7be843bSPierre Pronchery #define OP_INSERT  0
56*e7be843bSPierre Pronchery #define OP_DELETE  1
57*e7be843bSPierre Pronchery #define OP_LOOKUP  2
58*e7be843bSPierre Pronchery #define OP_FLUSH   3
59*e7be843bSPierre Pronchery #define OP_FOREACH 4
60*e7be843bSPierre Pronchery #define OP_FILTER  5
61*e7be843bSPierre Pronchery #define OP_END     6
62*e7be843bSPierre Pronchery 
63*e7be843bSPierre Pronchery #define OP_MASK 0x3f
64*e7be843bSPierre Pronchery #define INSERT_REPLACE_MASK 0x40
65*e7be843bSPierre Pronchery #define OPERATION(x) (((x) & OP_MASK) % OP_END)
66*e7be843bSPierre Pronchery #define IS_REPLACE(x) ((x) & INSERT_REPLACE_MASK)
67*e7be843bSPierre Pronchery 
table_iterator(HT_VALUE * v,void * arg)68*e7be843bSPierre Pronchery static int table_iterator(HT_VALUE *v, void *arg)
69*e7be843bSPierre Pronchery {
70*e7be843bSPierre Pronchery     uint16_t keyval = (*(uint16_t *)arg);
71*e7be843bSPierre Pronchery     FUZZER_VALUE *f = ossl_ht_fz_FUZZER_VALUE_from_value(v);
72*e7be843bSPierre Pronchery 
73*e7be843bSPierre Pronchery     if (f != NULL && f == &prediction_table[keyval]) {
74*e7be843bSPierre Pronchery         valfound = 1;
75*e7be843bSPierre Pronchery         return 0;
76*e7be843bSPierre Pronchery     }
77*e7be843bSPierre Pronchery 
78*e7be843bSPierre Pronchery     return 1;
79*e7be843bSPierre Pronchery }
80*e7be843bSPierre Pronchery 
filter_iterator(HT_VALUE * v,void * arg)81*e7be843bSPierre Pronchery static int filter_iterator(HT_VALUE *v, void *arg)
82*e7be843bSPierre Pronchery {
83*e7be843bSPierre Pronchery     uint16_t keyval = (*(uint16_t *)arg);
84*e7be843bSPierre Pronchery     FUZZER_VALUE *f = ossl_ht_fz_FUZZER_VALUE_from_value(v);
85*e7be843bSPierre Pronchery 
86*e7be843bSPierre Pronchery     if (f != NULL && f == &prediction_table[keyval])
87*e7be843bSPierre Pronchery         return 1;
88*e7be843bSPierre Pronchery 
89*e7be843bSPierre Pronchery     return 0;
90*e7be843bSPierre Pronchery }
91*e7be843bSPierre Pronchery 
fuzz_free_cb(HT_VALUE * v)92*e7be843bSPierre Pronchery static void fuzz_free_cb(HT_VALUE *v)
93*e7be843bSPierre Pronchery {
94*e7be843bSPierre Pronchery     FUZZER_VALUE *f = ossl_ht_fz_FUZZER_VALUE_from_value(v);
95*e7be843bSPierre Pronchery 
96*e7be843bSPierre Pronchery     if (f != NULL)
97*e7be843bSPierre Pronchery         f->flags &= ~FZ_FLAG_ALLOCATED;
98*e7be843bSPierre Pronchery }
99*e7be843bSPierre Pronchery 
FuzzerInitialize(int * argc,char *** argv)100*e7be843bSPierre Pronchery int FuzzerInitialize(int *argc, char ***argv)
101*e7be843bSPierre Pronchery {
102*e7be843bSPierre Pronchery     HT_CONFIG fuzz_conf = {NULL, fuzz_free_cb, NULL, 0, 1};
103*e7be843bSPierre Pronchery 
104*e7be843bSPierre Pronchery     OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
105*e7be843bSPierre Pronchery     ERR_clear_error();
106*e7be843bSPierre Pronchery     prediction_table = OPENSSL_zalloc(sizeof(FUZZER_VALUE) * 65537);
107*e7be843bSPierre Pronchery     if (prediction_table == NULL)
108*e7be843bSPierre Pronchery         return -1;
109*e7be843bSPierre Pronchery     fuzzer_table = ossl_ht_new(&fuzz_conf);
110*e7be843bSPierre Pronchery     if (fuzzer_table == NULL) {
111*e7be843bSPierre Pronchery         OPENSSL_free(prediction_table);
112*e7be843bSPierre Pronchery         return -1;
113*e7be843bSPierre Pronchery     }
114*e7be843bSPierre Pronchery 
115*e7be843bSPierre Pronchery     return 0;
116*e7be843bSPierre Pronchery }
117*e7be843bSPierre Pronchery 
FuzzerTestOneInput(const uint8_t * buf,size_t len)118*e7be843bSPierre Pronchery int FuzzerTestOneInput(const uint8_t *buf, size_t len)
119*e7be843bSPierre Pronchery {
120*e7be843bSPierre Pronchery     uint8_t op_flags;
121*e7be843bSPierre Pronchery     uint16_t keyval;
122*e7be843bSPierre Pronchery     int rc;
123*e7be843bSPierre Pronchery     int rc_prediction = 1;
124*e7be843bSPierre Pronchery     size_t i;
125*e7be843bSPierre Pronchery     FUZZER_VALUE *valptr, *lval;
126*e7be843bSPierre Pronchery     FUZZER_KEY key;
127*e7be843bSPierre Pronchery     HT_VALUE *v = NULL;
128*e7be843bSPierre Pronchery     HT_VALUE tv;
129*e7be843bSPierre Pronchery     HT_VALUE_LIST *htvlist;
130*e7be843bSPierre Pronchery 
131*e7be843bSPierre Pronchery     /*
132*e7be843bSPierre Pronchery      * We need at least 11 bytes to be able to do anything here
133*e7be843bSPierre Pronchery      * 1 byte to detect the operation to perform, 2 bytes
134*e7be843bSPierre Pronchery      * for the lookup key, and 8 bytes of value
135*e7be843bSPierre Pronchery      */
136*e7be843bSPierre Pronchery     if (len < 11) {
137*e7be843bSPierre Pronchery         skipped_values++;
138*e7be843bSPierre Pronchery         return -1;
139*e7be843bSPierre Pronchery     }
140*e7be843bSPierre Pronchery 
141*e7be843bSPierre Pronchery     /*
142*e7be843bSPierre Pronchery      * parse out our operation flags and key
143*e7be843bSPierre Pronchery      */
144*e7be843bSPierre Pronchery     op_flags = buf[0];
145*e7be843bSPierre Pronchery     memcpy(&keyval, &buf[1], sizeof(uint16_t));
146*e7be843bSPierre Pronchery 
147*e7be843bSPierre Pronchery     /*
148*e7be843bSPierre Pronchery      * Initialize our key
149*e7be843bSPierre Pronchery      */
150*e7be843bSPierre Pronchery     HT_INIT_KEY(&key);
151*e7be843bSPierre Pronchery 
152*e7be843bSPierre Pronchery     /*
153*e7be843bSPierre Pronchery      * Now do our operation
154*e7be843bSPierre Pronchery      */
155*e7be843bSPierre Pronchery     switch(OPERATION(op_flags)) {
156*e7be843bSPierre Pronchery     case OP_INSERT:
157*e7be843bSPierre Pronchery         valptr = &prediction_table[keyval];
158*e7be843bSPierre Pronchery 
159*e7be843bSPierre Pronchery         /* reset our key */
160*e7be843bSPierre Pronchery         HT_KEY_RESET(&key);
161*e7be843bSPierre Pronchery 
162*e7be843bSPierre Pronchery         /* set the proper key value */
163*e7be843bSPierre Pronchery         HT_SET_KEY_FIELD(&key, fuzzkey, keyval);
164*e7be843bSPierre Pronchery 
165*e7be843bSPierre Pronchery         /* lock the table */
166*e7be843bSPierre Pronchery         ossl_ht_write_lock(fuzzer_table);
167*e7be843bSPierre Pronchery 
168*e7be843bSPierre Pronchery         /*
169*e7be843bSPierre Pronchery          * If the value to insert is already allocated
170*e7be843bSPierre Pronchery          * then we expect a conflict in the insert
171*e7be843bSPierre Pronchery          * i.e. we predict a return code of 0 instead
172*e7be843bSPierre Pronchery          * of 1. On replacement, we expect it to succeed
173*e7be843bSPierre Pronchery          * always
174*e7be843bSPierre Pronchery          */
175*e7be843bSPierre Pronchery         if (valptr->flags & FZ_FLAG_ALLOCATED) {
176*e7be843bSPierre Pronchery             if (!IS_REPLACE(op_flags))
177*e7be843bSPierre Pronchery                 rc_prediction = 0;
178*e7be843bSPierre Pronchery         }
179*e7be843bSPierre Pronchery 
180*e7be843bSPierre Pronchery         memcpy(&valptr->value, &buf[3], sizeof(uint64_t));
181*e7be843bSPierre Pronchery         /*
182*e7be843bSPierre Pronchery          * do the insert/replace
183*e7be843bSPierre Pronchery          */
184*e7be843bSPierre Pronchery         if (IS_REPLACE(op_flags))
185*e7be843bSPierre Pronchery             rc = ossl_ht_fz_FUZZER_VALUE_insert(fuzzer_table, TO_HT_KEY(&key),
186*e7be843bSPierre Pronchery                                                 valptr, &lval);
187*e7be843bSPierre Pronchery         else
188*e7be843bSPierre Pronchery             rc = ossl_ht_fz_FUZZER_VALUE_insert(fuzzer_table, TO_HT_KEY(&key),
189*e7be843bSPierre Pronchery                                                 valptr, NULL);
190*e7be843bSPierre Pronchery 
191*e7be843bSPierre Pronchery         if (rc == -1)
192*e7be843bSPierre Pronchery             /* failed to grow the hash table due to too many collisions */
193*e7be843bSPierre Pronchery             break;
194*e7be843bSPierre Pronchery 
195*e7be843bSPierre Pronchery         /*
196*e7be843bSPierre Pronchery          * mark the entry as being allocated
197*e7be843bSPierre Pronchery          */
198*e7be843bSPierre Pronchery         valptr->flags |= FZ_FLAG_ALLOCATED;
199*e7be843bSPierre Pronchery 
200*e7be843bSPierre Pronchery         /*
201*e7be843bSPierre Pronchery          * unlock the table
202*e7be843bSPierre Pronchery          */
203*e7be843bSPierre Pronchery         ossl_ht_write_unlock(fuzzer_table);
204*e7be843bSPierre Pronchery 
205*e7be843bSPierre Pronchery         /*
206*e7be843bSPierre Pronchery          * Now check to make sure we did the right thing
207*e7be843bSPierre Pronchery          */
208*e7be843bSPierre Pronchery         OPENSSL_assert(rc == rc_prediction);
209*e7be843bSPierre Pronchery 
210*e7be843bSPierre Pronchery         /*
211*e7be843bSPierre Pronchery          * successful insertion if there wasn't a conflict
212*e7be843bSPierre Pronchery          */
213*e7be843bSPierre Pronchery         if (rc_prediction == 1)
214*e7be843bSPierre Pronchery             IS_REPLACE(op_flags) ? replacements++ : inserts++;
215*e7be843bSPierre Pronchery         break;
216*e7be843bSPierre Pronchery 
217*e7be843bSPierre Pronchery     case OP_DELETE:
218*e7be843bSPierre Pronchery         valptr = &prediction_table[keyval];
219*e7be843bSPierre Pronchery 
220*e7be843bSPierre Pronchery         /* reset our key */
221*e7be843bSPierre Pronchery         HT_KEY_RESET(&key);
222*e7be843bSPierre Pronchery 
223*e7be843bSPierre Pronchery         /* set the proper key value */
224*e7be843bSPierre Pronchery         HT_SET_KEY_FIELD(&key, fuzzkey, keyval);
225*e7be843bSPierre Pronchery 
226*e7be843bSPierre Pronchery         /* lock the table */
227*e7be843bSPierre Pronchery         ossl_ht_write_lock(fuzzer_table);
228*e7be843bSPierre Pronchery 
229*e7be843bSPierre Pronchery         /*
230*e7be843bSPierre Pronchery          * If the value to delete is not already allocated
231*e7be843bSPierre Pronchery          * then we expect a miss in the delete
232*e7be843bSPierre Pronchery          * i.e. we predict a return code of 0 instead
233*e7be843bSPierre Pronchery          * of 1
234*e7be843bSPierre Pronchery          */
235*e7be843bSPierre Pronchery         if (!(valptr->flags & FZ_FLAG_ALLOCATED))
236*e7be843bSPierre Pronchery             rc_prediction = 0;
237*e7be843bSPierre Pronchery 
238*e7be843bSPierre Pronchery         /*
239*e7be843bSPierre Pronchery          * do the delete
240*e7be843bSPierre Pronchery          */
241*e7be843bSPierre Pronchery         rc = ossl_ht_delete(fuzzer_table, TO_HT_KEY(&key));
242*e7be843bSPierre Pronchery 
243*e7be843bSPierre Pronchery         /*
244*e7be843bSPierre Pronchery          * unlock the table
245*e7be843bSPierre Pronchery          */
246*e7be843bSPierre Pronchery         ossl_ht_write_unlock(fuzzer_table);
247*e7be843bSPierre Pronchery 
248*e7be843bSPierre Pronchery         /*
249*e7be843bSPierre Pronchery          * Now check to make sure we did the right thing
250*e7be843bSPierre Pronchery          */
251*e7be843bSPierre Pronchery         OPENSSL_assert(rc == rc_prediction);
252*e7be843bSPierre Pronchery 
253*e7be843bSPierre Pronchery         /*
254*e7be843bSPierre Pronchery          * once the unlock is done, the table rcu will have synced
255*e7be843bSPierre Pronchery          * meaning the free function has run, so we can confirm now
256*e7be843bSPierre Pronchery          * that the valptr is no longer allocated
257*e7be843bSPierre Pronchery          */
258*e7be843bSPierre Pronchery         OPENSSL_assert(!(valptr->flags & FZ_FLAG_ALLOCATED));
259*e7be843bSPierre Pronchery 
260*e7be843bSPierre Pronchery         /*
261*e7be843bSPierre Pronchery          * successful deletion if there wasn't a conflict
262*e7be843bSPierre Pronchery          */
263*e7be843bSPierre Pronchery         if (rc_prediction == 1)
264*e7be843bSPierre Pronchery             deletes++;
265*e7be843bSPierre Pronchery 
266*e7be843bSPierre Pronchery         break;
267*e7be843bSPierre Pronchery 
268*e7be843bSPierre Pronchery     case OP_LOOKUP:
269*e7be843bSPierre Pronchery         valptr = &prediction_table[keyval];
270*e7be843bSPierre Pronchery         lval = NULL;
271*e7be843bSPierre Pronchery 
272*e7be843bSPierre Pronchery         /* reset our key */
273*e7be843bSPierre Pronchery         HT_KEY_RESET(&key);
274*e7be843bSPierre Pronchery 
275*e7be843bSPierre Pronchery         /* set the proper key value */
276*e7be843bSPierre Pronchery         HT_SET_KEY_FIELD(&key, fuzzkey, keyval);
277*e7be843bSPierre Pronchery 
278*e7be843bSPierre Pronchery         /* lock the table for reading */
279*e7be843bSPierre Pronchery         ossl_ht_read_lock(fuzzer_table);
280*e7be843bSPierre Pronchery 
281*e7be843bSPierre Pronchery         /*
282*e7be843bSPierre Pronchery          * If the value to find is not already allocated
283*e7be843bSPierre Pronchery          * then we expect a miss in the lookup
284*e7be843bSPierre Pronchery          * i.e. we predict a return code of NULL instead
285*e7be843bSPierre Pronchery          * of a pointer
286*e7be843bSPierre Pronchery          */
287*e7be843bSPierre Pronchery         if (!(valptr->flags & FZ_FLAG_ALLOCATED))
288*e7be843bSPierre Pronchery             valptr = NULL;
289*e7be843bSPierre Pronchery 
290*e7be843bSPierre Pronchery         /*
291*e7be843bSPierre Pronchery          * do the lookup
292*e7be843bSPierre Pronchery          */
293*e7be843bSPierre Pronchery         lval = ossl_ht_fz_FUZZER_VALUE_get(fuzzer_table, TO_HT_KEY(&key), &v);
294*e7be843bSPierre Pronchery 
295*e7be843bSPierre Pronchery         /*
296*e7be843bSPierre Pronchery          * unlock the table
297*e7be843bSPierre Pronchery          */
298*e7be843bSPierre Pronchery         ossl_ht_read_unlock(fuzzer_table);
299*e7be843bSPierre Pronchery 
300*e7be843bSPierre Pronchery         /*
301*e7be843bSPierre Pronchery          * Now check to make sure we did the right thing
302*e7be843bSPierre Pronchery          */
303*e7be843bSPierre Pronchery         OPENSSL_assert(lval == valptr);
304*e7be843bSPierre Pronchery 
305*e7be843bSPierre Pronchery         /*
306*e7be843bSPierre Pronchery          * if we expect a positive lookup, make sure that
307*e7be843bSPierre Pronchery          * we can use the _type and to_value functions
308*e7be843bSPierre Pronchery          */
309*e7be843bSPierre Pronchery         if (valptr != NULL) {
310*e7be843bSPierre Pronchery             OPENSSL_assert(ossl_ht_fz_FUZZER_VALUE_type(v) == 1);
311*e7be843bSPierre Pronchery 
312*e7be843bSPierre Pronchery             v = ossl_ht_fz_FUZZER_VALUE_to_value(lval, &tv);
313*e7be843bSPierre Pronchery             OPENSSL_assert(v->value == lval);
314*e7be843bSPierre Pronchery         }
315*e7be843bSPierre Pronchery 
316*e7be843bSPierre Pronchery         /*
317*e7be843bSPierre Pronchery          * successful lookup if we didn't expect a miss
318*e7be843bSPierre Pronchery          */
319*e7be843bSPierre Pronchery         if (valptr != NULL)
320*e7be843bSPierre Pronchery             lookups++;
321*e7be843bSPierre Pronchery 
322*e7be843bSPierre Pronchery         break;
323*e7be843bSPierre Pronchery 
324*e7be843bSPierre Pronchery     case OP_FLUSH:
325*e7be843bSPierre Pronchery         /*
326*e7be843bSPierre Pronchery          * only flush the table rarely
327*e7be843bSPierre Pronchery          */
328*e7be843bSPierre Pronchery         if ((flushes % 100000) != 1) {
329*e7be843bSPierre Pronchery             skipped_values++;
330*e7be843bSPierre Pronchery             flushes++;
331*e7be843bSPierre Pronchery             return 0;
332*e7be843bSPierre Pronchery         }
333*e7be843bSPierre Pronchery 
334*e7be843bSPierre Pronchery         /*
335*e7be843bSPierre Pronchery          * lock the table
336*e7be843bSPierre Pronchery          */
337*e7be843bSPierre Pronchery         ossl_ht_write_lock(fuzzer_table);
338*e7be843bSPierre Pronchery         ossl_ht_flush(fuzzer_table);
339*e7be843bSPierre Pronchery         ossl_ht_write_unlock(fuzzer_table);
340*e7be843bSPierre Pronchery 
341*e7be843bSPierre Pronchery         /*
342*e7be843bSPierre Pronchery          * now check to make sure everything is free
343*e7be843bSPierre Pronchery          */
344*e7be843bSPierre Pronchery        for (i = 0; i < USHRT_MAX; i++)
345*e7be843bSPierre Pronchery             OPENSSL_assert((prediction_table[i].flags & FZ_FLAG_ALLOCATED) == 0);
346*e7be843bSPierre Pronchery 
347*e7be843bSPierre Pronchery         /* good flush */
348*e7be843bSPierre Pronchery         flushes++;
349*e7be843bSPierre Pronchery         break;
350*e7be843bSPierre Pronchery 
351*e7be843bSPierre Pronchery     case OP_FOREACH:
352*e7be843bSPierre Pronchery         valfound = 0;
353*e7be843bSPierre Pronchery         valptr = &prediction_table[keyval];
354*e7be843bSPierre Pronchery 
355*e7be843bSPierre Pronchery         rc_prediction = 0;
356*e7be843bSPierre Pronchery         if (valptr->flags & FZ_FLAG_ALLOCATED)
357*e7be843bSPierre Pronchery             rc_prediction = 1;
358*e7be843bSPierre Pronchery 
359*e7be843bSPierre Pronchery         ossl_ht_foreach_until(fuzzer_table, table_iterator, &keyval);
360*e7be843bSPierre Pronchery 
361*e7be843bSPierre Pronchery         OPENSSL_assert(valfound == rc_prediction);
362*e7be843bSPierre Pronchery 
363*e7be843bSPierre Pronchery         foreaches++;
364*e7be843bSPierre Pronchery         break;
365*e7be843bSPierre Pronchery 
366*e7be843bSPierre Pronchery     case OP_FILTER:
367*e7be843bSPierre Pronchery         valptr = &prediction_table[keyval];
368*e7be843bSPierre Pronchery 
369*e7be843bSPierre Pronchery         rc_prediction = 0;
370*e7be843bSPierre Pronchery         if (valptr->flags & FZ_FLAG_ALLOCATED)
371*e7be843bSPierre Pronchery             rc_prediction = 1;
372*e7be843bSPierre Pronchery 
373*e7be843bSPierre Pronchery         htvlist = ossl_ht_filter(fuzzer_table, 1, filter_iterator, &keyval);
374*e7be843bSPierre Pronchery 
375*e7be843bSPierre Pronchery         OPENSSL_assert(htvlist->list_len == (size_t)rc_prediction);
376*e7be843bSPierre Pronchery 
377*e7be843bSPierre Pronchery         ossl_ht_value_list_free(htvlist);
378*e7be843bSPierre Pronchery         filters++;
379*e7be843bSPierre Pronchery         break;
380*e7be843bSPierre Pronchery 
381*e7be843bSPierre Pronchery     default:
382*e7be843bSPierre Pronchery         return -1;
383*e7be843bSPierre Pronchery     }
384*e7be843bSPierre Pronchery 
385*e7be843bSPierre Pronchery     return 0;
386*e7be843bSPierre Pronchery }
387*e7be843bSPierre Pronchery 
FuzzerCleanup(void)388*e7be843bSPierre Pronchery void FuzzerCleanup(void)
389*e7be843bSPierre Pronchery {
390*e7be843bSPierre Pronchery     ossl_ht_free(fuzzer_table);
391*e7be843bSPierre Pronchery     OPENSSL_free(prediction_table);
392*e7be843bSPierre Pronchery     OPENSSL_cleanup();
393*e7be843bSPierre Pronchery }
394