OLD | NEW |
(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 |
OLD | NEW |