Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: patches.chromium/0006-fix_lhash_iteration.patch

Issue 57833003: Fix lhash implementation to avoid unwanted resizes during iteration. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/openssl@master
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« openssl/crypto/lhash/lhash.c ('K') | « openssl/ssl/ssl_sess.c ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 diff -burN android-openssl.org/crypto/conf/conf_api.c android-openssl/crypto/con f/conf_api.c
2 --- android-openssl.org/crypto/conf/conf_api.c 2013-11-04 14:55:20.473482962 +0 100
3 +++ android-openssl/crypto/conf/conf_api.c 2013-11-04 14:55:26.643552646 +0 100
4 @@ -225,9 +225,6 @@
5 {
6 if (conf == NULL || conf->data == NULL) return;
7
8 - lh_CONF_VALUE_down_load(conf->data)=0; /* evil thing to make
9 - * sure the 'OPENSSL_free()' works as
10 - * expected */
11 lh_CONF_VALUE_doall_arg(conf->data,
12 LHASH_DOALL_ARG_FN(value_free_hash),
13 LHASH_OF(CONF_VALUE), conf->data);
14 diff -burN android-openssl.org/crypto/lhash/lhash.c android-openssl/crypto/lhash /lhash.c
15 --- android-openssl.org/crypto/lhash/lhash.c 2013-11-04 14:55:20.483483075 +0 100
16 +++ android-openssl/crypto/lhash/lhash.c 2013-11-04 14:55:26.643552646 +0 100
17 @@ -94,6 +94,7 @@
18 *
19 * 1.0 eay - First version
20 */
21 +#include <limits.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 @@ -107,6 +108,113 @@
26 #define UP_LOAD (2*LH_LOAD_MULT) /* load times 256 (default 2) */
27 #define DOWN_LOAD (LH_LOAD_MULT) /* load times 256 (default 1) */
28
29 +/* Maximum number of nodes to guarantee the load computations don't overflow */
30 +#define MAX_LOAD_ITEMS (UINT_MAX / LH_LOAD_MULT)
31 +
32 +/* The field 'iteration_state' is used to hold data to ensure that a hash
33 + * table is not resized during an 'insert' or 'delete' operation performed
34 + * within a lh_doall/lh_doall_arg call.
35 + *
36 + * Conceptually, this records two things:
37 + *
38 + * - A 'depth' count, which is incremented at the start of lh_doall*,
39 + * and decremented just before it returns.
40 + *
41 + * - A 'mutated' boolean flag, which is set in lh_insert() or lh_delete()
42 + * when the operation is performed with a non-0 depth.
43 + *
44 + * The following are helper macros to handle this state in a more explicit
45 + * way.
46 + */
47 +
48 +/* Reset the iteration state to its defaults. */
49 +#define LH_ITERATION_RESET(lh) do { \
50 + (lh)->iteration_state = 0; \
51 + } while (0)
52 +
53 +/* Returns 1 if the hash table is currently being iterated on, 0 otherwise. */
54 +#define LH_ITERATION_IS_ACTIVE(lh) ((lh)->iteration_state >= 2)
55 +
56 +/* Increment iteration depth. This should always be followed by a paired call
57 + * to LH_ITERATION_DECREMENT_DEPTH(). */
58 +#define LH_ITERATION_INCREMENT_DEPTH(lh) do { \
59 + (lh)->iteration_state += 2; \
60 + } while (0)
61 +
62 +/* Decrement iteration depth. This should always be called after a paired call
63 + * to LH_ITERATION_INCREMENT_DEPTH(). */
64 +#define LH_ITERATION_DECREMENT_DEPTH(lh) do { \
65 + (lh)->iteration_state -= 2; \
66 + } while (0)
67 +
68 +/* Return 1 if the iteration 'mutated' flag is set, 0 otherwise. */
69 +#define LH_ITERATION_IS_MUTATED(lh) (((lh)->iteration_state & 1) != 0)
70 +
71 +/* Set the iteration 'mutated' flag to 1. LH_ITERATION_RESET() to reset it. */
72 +#define LH_ITERATION_SET_MUTATED(lh) do { \
73 + (lh)->iteration_state |= 1; \
74 + } while (0)
75 +
76 +/* This macros returns 1 if the hash table should be expanded due to its curren t
77 + * load, or 0 otherwise. The exact comparison to be performed is expressed by
78 + * the mathematical expression (where '//' denotes the exact division operation ):
79 + *
80 + * (num_items // num_nodes) >= (up_load // LOAD_MULT) or
81 + * (num_items * LOAD_MULT // num_nodes) >= up_load.
82 + *
83 + * Given that the C language operator '/' implements integer division, i.e:
84 + * a // b == (a / b) + epsilon (with 0 <= epsilon < 1, for positive a & b)
85 + *
86 + * This can be rewritten as:
87 + * (num_items * LOAD_MULT / num_nodes) + epsilon >= up_load
88 + * (num_items * LOAD_MULT / num_nodes) - up_load >= - epsilon
89 + *
90 + * Let's call 'A' the left-hand side of the equation above, it is an integer
91 + * and:
92 + * - If A >= 0, the expression is true for any value of epsilon.
93 + * - If A <= -1, the expression is also true for any value of epsilon.
94 + *
95 + * In other words, this is equivalent to 'A >= 0', or:
96 + * (num_items * LOAD_MULT / num_nodes) >= up_load
97 + */
98 +#define LH_SHOULD_EXPAND(lh) \
99 + ((lh)->num_items < MAX_LOAD_ITEMS && \
100 + (((lh)->num_items*LH_LOAD_MULT/(lh)->num_nodes) >= (lh)->up_load))
101 +
102 +/* This macro returns 1 if the hash table should be contracted due to its
103 + * current load, or 0 otherwise. Abbreviated computations are:
104 + *
105 + * (num_items // num_nodes) <= (down_load // LOAD_MULT)
106 + * (num_items * LOAD_MULT // num_nodes) <= down_load
107 + * (num_items * LOAD_MULT / num_nodes) + epsilon <= down_load
108 + * (num_items * LOAD_MULT / num_nodes) - down_load <= -epsilon
109 + *
110 + * Let's call 'B' the left-hand side of the equation above:
111 + * - If B <= -1, the expression is true for any value of epsilon.
112 + * - If B >= 1, the expression is false for any value of epsilon.
113 + * - If B == 0, the expression is true for 'epsilon == 0', and false
114 + * otherwise, which is problematic.
115 + *
116 + * To work around this problem, while keeping the code simple, just change
117 + * the initial expression to use a strict inequality, i.e.:
118 + *
119 + * (num_items // num_nodes) < (down_load // LOAD_MULT)
120 + *
121 + * Which leads to:
122 + * (num_items * LOAD_MULT / num_nodes) - down_load < -epsilon
123 + *
124 + * Then:
125 + * - If 'B <= -1', the expression is true for any value of epsilon.
126 + * - If 'B' >= 0, the expression is false for any value of epsilon,
127 + *
128 + * In other words, this is equivalent to 'B < 0', or:
129 + * (num_items * LOAD_MULT / num_nodes) < down_load
130 + */
131 +#define LH_SHOULD_CONTRACT(lh) \
132 + (((lh)->num_nodes > MIN_NODES) && \
133 + ((lh)->num_items < MAX_LOAD_ITEMS && \
134 + ((lh)->num_items*LH_LOAD_MULT/(lh)->num_nodes) < (lh)->down_load))
135 +
136 static void expand(_LHASH *lh);
137 static void contract(_LHASH *lh);
138 static LHASH_NODE **getrn(_LHASH *lh, const void *data, unsigned long *rhash);
139 @@ -147,6 +255,7 @@
140 ret->num_hash_comps=0;
141
142 ret->error=0;
143 + LH_ITERATION_RESET(ret);
144 return(ret);
145 err1:
146 OPENSSL_free(ret);
147 @@ -183,7 +292,10 @@
148 void *ret;
149
150 lh->error=0;
151 - if (lh->up_load <= (lh->num_items*LH_LOAD_MULT/lh->num_nodes))
152 + /* Do not expand the array if the table is being iterated on. */
153 + if (LH_ITERATION_IS_ACTIVE(lh))
154 + LH_ITERATION_SET_MUTATED(lh);
155 + else if (LH_SHOULD_EXPAND(lh))
156 expand(lh);
157
158 rn=getrn(lh,data,&hash);
159 @@ -238,8 +350,10 @@
160 }
161
162 lh->num_items--;
163 - if ((lh->num_nodes > MIN_NODES) &&
164 - (lh->down_load >= (lh->num_items*LH_LOAD_MULT/lh->num_nodes)))
165 + /* Do not contract the array if the table is being iterated on. */
166 + if (LH_ITERATION_IS_ACTIVE(lh))
167 + LH_ITERATION_SET_MUTATED(lh);
168 + else if (LH_SHOULD_CONTRACT(lh))
169 contract(lh);
170
171 return(ret);
172 @@ -276,6 +390,7 @@
173 if (lh == NULL)
174 return;
175
176 + LH_ITERATION_INCREMENT_DEPTH(lh);
177 /* reverse the order so we search from 'top to bottom'
178 * We were having memory leaks otherwise */
179 for (i=lh->num_nodes-1; i>=0; i--)
180 @@ -295,6 +410,19 @@
181 a=n;
182 }
183 }
184 +
185 + LH_ITERATION_DECREMENT_DEPTH(lh);
186 + if (!LH_ITERATION_IS_ACTIVE(lh) && LH_ITERATION_IS_MUTATED(lh))
187 + {
188 + LH_ITERATION_RESET(lh);
189 + /* Resize the buckets array if necessary. Each expand() or
190 + * contract() call will double/halve the size of the array,
191 + * respectively, so call them in a loop. */
192 + while (LH_SHOULD_EXPAND(lh))
193 + expand(lh);
194 + while (LH_SHOULD_CONTRACT(lh))
195 + contract(lh);
196 + }
197 }
198
199 void lh_doall(_LHASH *lh, LHASH_DOALL_FN_TYPE func)
200 diff -burN android-openssl.org/crypto/lhash/lhash.h android-openssl/crypto/lhash /lhash.h
201 --- android-openssl.org/crypto/lhash/lhash.h 2013-11-04 14:55:20.483483075 +0 100
202 +++ android-openssl/crypto/lhash/lhash.h 2013-11-04 14:55:26.643552646 +0 100
203 @@ -163,6 +163,7 @@
204 unsigned long num_hash_comps;
205
206 int error;
207 + int iteration_state;
208 } _LHASH; /* Do not use _LHASH directly, use LHASH_OF
209 * and friends */
210
211 diff -burN android-openssl.org/crypto/objects/obj_dat.c android-openssl/crypto/o bjects/obj_dat.c
212 --- android-openssl.org/crypto/objects/obj_dat.c 2013-11-04 14:55:20.4934 83188 +0100
213 +++ android-openssl/crypto/objects/obj_dat.c 2013-11-04 14:55:26.643552646 +0 100
214 @@ -227,7 +227,6 @@
215 return ;
216 }
217 if (added == NULL) return;
218 - lh_ADDED_OBJ_down_load(added) = 0;
219 lh_ADDED_OBJ_doall(added,LHASH_DOALL_FN(cleanup1)); /* zero counters */
220 lh_ADDED_OBJ_doall(added,LHASH_DOALL_FN(cleanup2)); /* set counters */
221 lh_ADDED_OBJ_doall(added,LHASH_DOALL_FN(cleanup3)); /* free objects */
222 diff -burN android-openssl.org/crypto/objects/o_names.c android-openssl/crypto/o bjects/o_names.c
223 --- android-openssl.org/crypto/objects/o_names.c 2013-11-04 14:55:20.4934 83188 +0100
224 +++ android-openssl/crypto/objects/o_names.c 2013-11-04 14:55:26.643552646 +0 100
225 @@ -350,13 +350,9 @@
226
227 void OBJ_NAME_cleanup(int type)
228 {
229 - unsigned long down_load;
230 -
231 if (names_lh == NULL) return;
232
233 free_type=type;
234 - down_load=lh_OBJ_NAME_down_load(names_lh);
235 - lh_OBJ_NAME_down_load(names_lh)=0;
236
237 lh_OBJ_NAME_doall(names_lh,LHASH_DOALL_FN(names_lh_free));
238 if (type < 0)
239 @@ -366,7 +362,5 @@
240 names_lh=NULL;
241 name_funcs_stack = NULL;
242 }
243 - else
244 - lh_OBJ_NAME_down_load(names_lh)=down_load;
245 }
246
247 diff -burN android-openssl.org/include/openssl/lhash.h android-openssl/include/o penssl/lhash.h
248 --- android-openssl.org/include/openssl/lhash.h 2013-11-04 14:55:20.503483301 +0 100
249 +++ android-openssl/include/openssl/lhash.h 2013-11-04 14:55:26.643552646 +0 100
250 @@ -163,6 +163,7 @@
251 unsigned long num_hash_comps;
252
253 int error;
254 + int iteration_state;
255 } _LHASH; /* Do not use _LHASH directly, use LHASH_OF
256 * and friends */
257
258 diff -burN android-openssl.org/openssl.config android-openssl/openssl.config
259 --- android-openssl.org/openssl.config 2013-11-04 14:55:20.503483301 +0100
260 +++ android-openssl/openssl.config 2013-11-04 14:59:05.916037366 +0100
261 @@ -997,6 +997,7 @@
262 fix_clang_build.patch \
263 x509_hash_name_algorithm_change.patch \
264 reduce_client_hello_size.patch \
265 +fix_lhash_iteration.patch \
266 "
267
268 OPENSSL_PATCHES_progs_SOURCES="\
269 @@ -1060,3 +1061,14 @@
270 OPENSSL_PATCHES_reduce_client_hello_size_SOURCES="\
271 ssl/t1_lib.c \
272 "
273 +
274 +OPENSSL_PATCHES_fix_lhash_iteration_SOURCES="\
275 +crypto/conf/conf_api.c
276 +crypto/lhash/lhash.c
277 +crypto/lhash/lhash.h
278 +crypto/objects/obj_dat.c
279 +crypto/objects/o_names.c
280 +include/openssl/lhash.h
281 +ssl/ssl_sess.c
282 +"
283 +
284 diff -burN android-openssl.org/patches/fix_lhash_iteration.patch android-openssl /patches/fix_lhash_iteration.patch
285 --- android-openssl.org/patches/fix_lhash_iteration.patch 1970-01-01 01:00 :00.000000000 +0100
286 +++ android-openssl/patches/fix_lhash_iteration.patch 2013-11-04 14:55:26.6435 52646 +0100
287 @@ -0,0 +1,326 @@
288 +From 84726440ecdd3ecd0c3d8571cc6a50bad769b5b8 Mon Sep 17 00:00:00 2001
289 +From: David 'Digit' Turner <digit@android.com>
290 +Date: Tue, 29 Oct 2013 18:40:45 +0100
291 +Subject: Ensure iterating over a lhash table prevents unwanted resizes.
292 +
293 +This patch modifies the implementation of lhash tables to ensure
294 +that deleting or inserting items during a lh_doall or lh_doall_arg
295 +call will not unexpectedly resize the buckets array, leading to
296 +undefined behaviour.
297 +
298 +This is done by adding a new field ('iteration_state') to the
299 +lhash_st structure. Note that the field is placed at the end
300 +of the structure to preserve the OpenSSL ABI [1]
301 +
302 +This also removes the 'evil' changes to the 'down_load' field,
303 +which were performed to prevent this. Unfortunately, this didn't
304 +work due to an incorrect load-comparison computation is
305 +lh_delete() [2]
306 +
307 +[1] Since all _LHASH objects are heap-allocated through lh_new(),
308 + client code that accesses fields directly will not be
309 + impacted if their offsets do not change.
310 +
311 +[2] The original code used the following expression to determine
312 + when to contract the table during a lh_delete() operation:
313 +
314 + down_load >= (num_items * LOAD_MULT / num_nodes)
315 +
316 + Unfortunately, due to truncation towards zero, this could
317 + trigger even when down_load was set to 0 in certain cases.
318 + See the comments for the LH_SHOULD_CONTRACT() macro for
319 + more explanations.
320 +
321 +Change-Id: I9fa5b84c5d787d41fd520b63f7e641cf22fbb5b6
322 +---
323 + crypto/conf/conf_api.c | 3 --
324 + crypto/lhash/lhash.c | 134 +++++++++++++++++++++++++++++++++++++++++++++--
325 + crypto/lhash/lhash.h | 3 +-
326 + crypto/objects/o_names.c | 6 ---
327 + crypto/objects/obj_dat.c | 1 -
328 + include/openssl/lhash.h | 1 +
329 + ssl/ssl_sess.c | 3 --
330 + 7 files changed, 134 insertions(+), 17 deletions(-)
331 +
332 +diff --git a/crypto/conf/conf_api.c b/crypto/conf/conf_api.c
333 +index f5fcbb9..9a37bd4 100644
334 +--- a/crypto/conf/conf_api.c
335 ++++ b/crypto/conf/conf_api.c
336 +@@ -225,9 +225,6 @@ void _CONF_free_data(CONF *conf)
337 + {
338 + if (conf == NULL || conf->data == NULL) return;
339 +
340 +- lh_CONF_VALUE_down_load(conf->data)=0; /* evil thing to make
341 +- * sure the 'OPENSSL_free()' works as
342 +- * expected */
343 + lh_CONF_VALUE_doall_arg(conf->data,
344 + LHASH_DOALL_ARG_FN(value_free_hash),
345 + LHASH_OF(CONF_VALUE), conf->data);
346 +diff --git a/crypto/lhash/lhash.c b/crypto/lhash/lhash.c
347 +index 47f7480..6278c54 100644
348 +--- a/crypto/lhash/lhash.c
349 ++++ b/crypto/lhash/lhash.c
350 +@@ -94,6 +94,7 @@
351 + *
352 + * 1.0 eay - First version
353 + */
354 ++#include <limits.h>
355 + #include <stdio.h>
356 + #include <string.h>
357 + #include <stdlib.h>
358 +@@ -107,6 +108,113 @@ const char lh_version[]="lhash" OPENSSL_VERSION_PTEXT;
359 + #define UP_LOAD (2*LH_LOAD_MULT) /* load times 256 (default 2) */
360 + #define DOWN_LOAD (LH_LOAD_MULT) /* load times 256 (default 1) */
361 +
362 ++/* Maximum number of nodes to guarantee the load computations don't overflow * /
363 ++#define MAX_LOAD_ITEMS (UINT_MAX / LH_LOAD_MULT)
364 ++
365 ++/* The field 'iteration_state' is used to hold data to ensure that a hash
366 ++ * table is not resized during an 'insert' or 'delete' operation performed
367 ++ * within a lh_doall/lh_doall_arg call.
368 ++ *
369 ++ * Conceptually, this records two things:
370 ++ *
371 ++ * - A 'depth' count, which is incremented at the start of lh_doall*,
372 ++ * and decremented just before it returns.
373 ++ *
374 ++ * - A 'mutated' boolean flag, which is set in lh_insert() or lh_delete()
375 ++ * when the operation is performed with a non-0 depth.
376 ++ *
377 ++ * The following are helper macros to handle this state in a more explicit
378 ++ * way.
379 ++ */
380 ++
381 ++/* Reset the iteration state to its defaults. */
382 ++#define LH_ITERATION_RESET(lh) do { \
383 ++ (lh)->iteration_state = 0; \
384 ++ } while (0)
385 ++
386 ++/* Returns 1 if the hash table is currently being iterated on, 0 otherwise. */
387 ++#define LH_ITERATION_IS_ACTIVE(lh) ((lh)->iteration_state >= 2)
388 ++
389 ++/* Increment iteration depth. This should always be followed by a paired call
390 ++ * to LH_ITERATION_DECREMENT_DEPTH(). */
391 ++#define LH_ITERATION_INCREMENT_DEPTH(lh) do { \
392 ++ (lh)->iteration_state += 2; \
393 ++ } while (0)
394 ++
395 ++/* Decrement iteration depth. This should always be called after a paired call
396 ++ * to LH_ITERATION_INCREMENT_DEPTH(). */
397 ++#define LH_ITERATION_DECREMENT_DEPTH(lh) do { \
398 ++ (lh)->iteration_state -= 2; \
399 ++ } while (0)
400 ++
401 ++/* Return 1 if the iteration 'mutated' flag is set, 0 otherwise. */
402 ++#define LH_ITERATION_IS_MUTATED(lh) (((lh)->iteration_state & 1) != 0)
403 ++
404 ++/* Set the iteration 'mutated' flag to 1. LH_ITERATION_RESET() to reset it. */
405 ++#define LH_ITERATION_SET_MUTATED(lh) do { \
406 ++ (lh)->iteration_state |= 1; \
407 ++ } while (0)
408 ++
409 ++/* This macros returns 1 if the hash table should be expanded due to its curre nt
410 ++ * load, or 0 otherwise. The exact comparison to be performed is expressed by
411 ++ * the mathematical expression (where '//' denotes the exact division operatio n):
412 ++ *
413 ++ * (num_items // num_nodes) >= (up_load // LOAD_MULT) or
414 ++ * (num_items * LOAD_MULT // num_nodes) >= up_load.
415 ++ *
416 ++ * Given that the C language operator '/' implements integer division, i.e:
417 ++ * a // b == (a / b) + epsilon (with 0 <= epsilon < 1, for positive a & b )
418 ++ *
419 ++ * This can be rewritten as:
420 ++ * (num_items * LOAD_MULT / num_nodes) + epsilon >= up_load
421 ++ * (num_items * LOAD_MULT / num_nodes) - up_load >= - epsilon
422 ++ *
423 ++ * Let's call 'A' the left-hand side of the equation above, it is an integer
424 ++ * and:
425 ++ * - If A >= 0, the expression is true for any value of epsilon.
426 ++ * - If A <= -1, the expression is also true for any value of epsilon.
427 ++ *
428 ++ * In other words, this is equivalent to 'A >= 0', or:
429 ++ * (num_items * LOAD_MULT / num_nodes) >= up_load
430 ++ */
431 ++#define LH_SHOULD_EXPAND(lh) \
432 ++ ((lh)->num_items < MAX_LOAD_ITEMS && \
433 ++ (((lh)->num_items*LH_LOAD_MULT/(lh)->num_nodes) >= (lh)->up_load))
434 ++
435 ++/* This macro returns 1 if the hash table should be contracted due to its
436 ++ * current load, or 0 otherwise. Abbreviated computations are:
437 ++ *
438 ++ * (num_items // num_nodes) <= (down_load // LOAD_MULT)
439 ++ * (num_items * LOAD_MULT // num_nodes) <= down_load
440 ++ * (num_items * LOAD_MULT / num_nodes) + epsilon <= down_load
441 ++ * (num_items * LOAD_MULT / num_nodes) - down_load <= -epsilon
442 ++ *
443 ++ * Let's call 'B' the left-hand side of the equation above:
444 ++ * - If B <= -1, the expression is true for any value of epsilon.
445 ++ * - If B >= 1, the expression is false for any value of epsilon.
446 ++ * - If B == 0, the expression is true for 'epsilon == 0', and false
447 ++ * otherwise, which is problematic.
448 ++ *
449 ++ * To work around this problem, while keeping the code simple, just change
450 ++ * the initial expression to use a strict inequality, i.e.:
451 ++ *
452 ++ * (num_items // num_nodes) < (down_load // LOAD_MULT)
453 ++ *
454 ++ * Which leads to:
455 ++ * (num_items * LOAD_MULT / num_nodes) - down_load < -epsilon
456 ++ *
457 ++ * Then:
458 ++ * - If 'B <= -1', the expression is true for any value of epsilon.
459 ++ * - If 'B' >= 0, the expression is false for any value of epsilon,
460 ++ *
461 ++ * In other words, this is equivalent to 'B < 0', or:
462 ++ * (num_items * LOAD_MULT / num_nodes) < down_load
463 ++ */
464 ++#define LH_SHOULD_CONTRACT(lh) \
465 ++ (((lh)->num_nodes > MIN_NODES) && \
466 ++ ((lh)->num_items < MAX_LOAD_ITEMS && \
467 ++ ((lh)->num_items*LH_LOAD_MULT/(lh)->num_nodes) < (lh)->down_load))
468 ++
469 + static void expand(_LHASH *lh);
470 + static void contract(_LHASH *lh);
471 + static LHASH_NODE **getrn(_LHASH *lh, const void *data, unsigned long *rhash);
472 +@@ -147,6 +255,7 @@ _LHASH *lh_new(LHASH_HASH_FN_TYPE h, LHASH_COMP_FN_TYPE c)
473 + ret->num_hash_comps=0;
474 +
475 + ret->error=0;
476 ++ LH_ITERATION_RESET(ret);
477 + return(ret);
478 + err1:
479 + OPENSSL_free(ret);
480 +@@ -183,7 +292,10 @@ void *lh_insert(_LHASH *lh, void *data)
481 + void *ret;
482 +
483 + lh->error=0;
484 +- if (lh->up_load <= (lh->num_items*LH_LOAD_MULT/lh->num_nodes))
485 ++ /* Do not expand the array if the table is being iterated on. */
486 ++ if (LH_ITERATION_IS_ACTIVE(lh))
487 ++ LH_ITERATION_SET_MUTATED(lh);
488 ++ else if (LH_SHOULD_EXPAND(lh))
489 + expand(lh);
490 +
491 + rn=getrn(lh,data,&hash);
492 +@@ -238,8 +350,10 @@ void *lh_delete(_LHASH *lh, const void *data)
493 + }
494 +
495 + lh->num_items--;
496 +- if ((lh->num_nodes > MIN_NODES) &&
497 +- (lh->down_load >= (lh->num_items*LH_LOAD_MULT/lh->num_nodes)))
498 ++ /* Do not contract the array if the table is being iterated on. */
499 ++ if (LH_ITERATION_IS_ACTIVE(lh))
500 ++ LH_ITERATION_SET_MUTATED(lh);
501 ++ else if (LH_SHOULD_CONTRACT(lh))
502 + contract(lh);
503 +
504 + return(ret);
505 +@@ -276,6 +390,7 @@ static void doall_util_fn(_LHASH *lh, int use_arg, LHASH_DO ALL_FN_TYPE func,
506 + if (lh == NULL)
507 + return;
508 +
509 ++ LH_ITERATION_INCREMENT_DEPTH(lh);
510 + /* reverse the order so we search from 'top to bottom'
511 + * We were having memory leaks otherwise */
512 + for (i=lh->num_nodes-1; i>=0; i--)
513 +@@ -295,6 +410,19 @@ static void doall_util_fn(_LHASH *lh, int use_arg, LHASH_D OALL_FN_TYPE func,
514 + a=n;
515 + }
516 + }
517 ++
518 ++ LH_ITERATION_DECREMENT_DEPTH(lh);
519 ++ if (!LH_ITERATION_IS_ACTIVE(lh) && LH_ITERATION_IS_MUTATED(lh))
520 ++ {
521 ++ LH_ITERATION_RESET(lh);
522 ++ /* Resize the buckets array if necessary. Each expand() or
523 ++ * contract() call will double/halve the size of the array,
524 ++ * respectively, so call them in a loop. */
525 ++ while (LH_SHOULD_EXPAND(lh))
526 ++ expand(lh);
527 ++ while (LH_SHOULD_CONTRACT(lh))
528 ++ contract(lh);
529 ++ }
530 + }
531 +
532 + void lh_doall(_LHASH *lh, LHASH_DOALL_FN_TYPE func)
533 +diff --git a/crypto/lhash/lhash.h b/crypto/lhash/lhash.h
534 +index e7d8763..40aa7a5 100644
535 +--- a/crypto/lhash/lhash.h
536 ++++ b/crypto/lhash/lhash.h
537 +@@ -163,6 +163,7 @@ typedef struct lhash_st
538 + unsigned long num_hash_comps;
539 +
540 + int error;
541 ++ int iteration_state;
542 + } _LHASH; /* Do not use _LHASH directly, use LHASH_OF
543 + * and friends */
544 +
545 +diff --git a/crypto/objects/o_names.c b/crypto/objects/o_names.c
546 +index 4a548c2..4e18045 100644
547 +--- a/crypto/objects/o_names.c
548 ++++ b/crypto/objects/o_names.c
549 +@@ -350,13 +350,9 @@ static void name_funcs_free(NAME_FUNCS *ptr)
550 +
551 + void OBJ_NAME_cleanup(int type)
552 + {
553 +- unsigned long down_load;
554 +-
555 + if (names_lh == NULL) return;
556 +
557 + free_type=type;
558 +- down_load=lh_OBJ_NAME_down_load(names_lh);
559 +- lh_OBJ_NAME_down_load(names_lh)=0;
560 +
561 + lh_OBJ_NAME_doall(names_lh,LHASH_DOALL_FN(names_lh_free));
562 + if (type < 0)
563 +@@ -366,7 +362,5 @@ void OBJ_NAME_cleanup(int type)
564 + names_lh=NULL;
565 + name_funcs_stack = NULL;
566 + }
567 +- else
568 +- lh_OBJ_NAME_down_load(names_lh)=down_load;
569 + }
570 +
571 +diff --git a/crypto/objects/obj_dat.c b/crypto/objects/obj_dat.c
572 +index 8a342ba..ef0512a 100644
573 +--- a/crypto/objects/obj_dat.c
574 ++++ b/crypto/objects/obj_dat.c
575 +@@ -227,7 +227,6 @@ void OBJ_cleanup(void)
576 + return ;
577 + }
578 + if (added == NULL) return;
579 +- lh_ADDED_OBJ_down_load(added) = 0;
580 + lh_ADDED_OBJ_doall(added,LHASH_DOALL_FN(cleanup1)); /* zero counters */
581 + lh_ADDED_OBJ_doall(added,LHASH_DOALL_FN(cleanup2)); /* set counters */
582 + lh_ADDED_OBJ_doall(added,LHASH_DOALL_FN(cleanup3)); /* free objects */
583 +diff --git a/include/openssl/lhash.h b/include/openssl/lhash.h
584 +index e7d8763..75386f2 100644
585 +--- a/include/openssl/lhash.h
586 ++++ b/include/openssl/lhash.h
587 +@@ -163,6 +163,7 @@ typedef struct lhash_st
588 + unsigned long num_hash_comps;
589 +
590 + int error;
591 ++ int iteration_state;
592 + } _LHASH; /* Do not use _LHASH directly, use LHASH_OF
593 + * and friends */
594 +
595 +diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
596 +index 920b763..447a37e 100644
597 +--- a/ssl/ssl_sess.c
598 ++++ b/ssl/ssl_sess.c
599 +@@ -999,11 +999,8 @@ void SSL_CTX_flush_sessions(SSL_CTX *s, long t)
600 + if (tp.cache == NULL) return;
601 + tp.time=t;
602 + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
603 +- i=CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load;
604 +- CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load=0;
605 + lh_SSL_SESSION_doall_arg(tp.cache, LHASH_DOALL_ARG_FN(timeout),
606 + TIMEOUT_PARAM, &tp);
607 +- CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load=i;
608 + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
609 + }
610 +
611 +--
612 +1.8.4.1
613 +
614 diff -burN android-openssl.org/ssl/ssl_sess.c android-openssl/ssl/ssl_sess.c
615 --- android-openssl.org/ssl/ssl_sess.c 2013-11-04 14:55:20.453482735 +0100
616 +++ android-openssl/ssl/ssl_sess.c 2013-11-04 14:55:26.643552646 +0100
617 @@ -999,11 +999,8 @@
618 if (tp.cache == NULL) return;
619 tp.time=t;
620 CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
621 - i=CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load;
622 - CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load=0;
623 lh_SSL_SESSION_doall_arg(tp.cache, LHASH_DOALL_ARG_FN(timeout),
624 TIMEOUT_PARAM, &tp);
625 - CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load=i;
626 CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
627 }
628
OLDNEW
« openssl/crypto/lhash/lhash.c ('K') | « openssl/ssl/ssl_sess.c ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698