| OLD | NEW |
| 1 /* crypto/ex_data.c */ | 1 /* crypto/ex_data.c */ |
| 2 | 2 |
| 3 /* | 3 /* |
| 4 * Overhaul notes; | 4 * Overhaul notes; |
| 5 * | 5 * |
| 6 * This code is now *mostly* thread-safe. It is now easier to understand in what | 6 * This code is now *mostly* thread-safe. It is now easier to understand in what |
| 7 * ways it is safe and in what ways it is not, which is an improvement. Firstly, | 7 * ways it is safe and in what ways it is not, which is an improvement. Firstly, |
| 8 * all per-class stacks and index-counters for ex_data are stored in the same | 8 * all per-class stacks and index-counters for ex_data are stored in the same |
| 9 * global LHASH table (keyed by class). This hash table uses locking for all | 9 * global LHASH table (keyed by class). This hash table uses locking for all |
| 10 * access with the exception of CRYPTO_cleanup_all_ex_data(), which must only be | 10 * access with the exception of CRYPTO_cleanup_all_ex_data(), which must only be |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 typedef struct st_ex_class_item { | 238 typedef struct st_ex_class_item { |
| 239 int class_index; | 239 int class_index; |
| 240 STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth; | 240 STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth; |
| 241 int meth_num; | 241 int meth_num; |
| 242 } EX_CLASS_ITEM; | 242 } EX_CLASS_ITEM; |
| 243 | 243 |
| 244 /* When assigning new class indexes, this is our counter */ | 244 /* When assigning new class indexes, this is our counter */ |
| 245 static int ex_class = CRYPTO_EX_INDEX_USER; | 245 static int ex_class = CRYPTO_EX_INDEX_USER; |
| 246 | 246 |
| 247 /* The global hash table of EX_CLASS_ITEM items */ | 247 /* The global hash table of EX_CLASS_ITEM items */ |
| 248 static LHASH *ex_data = NULL; | 248 DECLARE_LHASH_OF(EX_CLASS_ITEM); |
| 249 static LHASH_OF(EX_CLASS_ITEM) *ex_data = NULL; |
| 249 | 250 |
| 250 /* The callbacks required in the "ex_data" hash table */ | 251 /* The callbacks required in the "ex_data" hash table */ |
| 251 static unsigned long ex_hash_cb(const void *a_void) | 252 static unsigned long ex_class_item_hash(const EX_CLASS_ITEM *a) |
| 252 { | 253 { |
| 253 » return ((const EX_CLASS_ITEM *)a_void)->class_index; | 254 » return a->class_index; |
| 254 } | 255 } |
| 255 static int ex_cmp_cb(const void *a_void, const void *b_void) | 256 static IMPLEMENT_LHASH_HASH_FN(ex_class_item, EX_CLASS_ITEM) |
| 257 |
| 258 static int ex_class_item_cmp(const EX_CLASS_ITEM *a, const EX_CLASS_ITEM *b) |
| 256 { | 259 { |
| 257 » return (((const EX_CLASS_ITEM *)a_void)->class_index - | 260 » return a->class_index - b->class_index; |
| 258 » » ((const EX_CLASS_ITEM *)b_void)->class_index); | |
| 259 } | 261 } |
| 262 static IMPLEMENT_LHASH_COMP_FN(ex_class_item, EX_CLASS_ITEM) |
| 260 | 263 |
| 261 /* Internal functions used by the "impl_default" implementation to access the | 264 /* Internal functions used by the "impl_default" implementation to access the |
| 262 * state */ | 265 * state */ |
| 263 | 266 |
| 264 static int ex_data_check(void) | 267 static int ex_data_check(void) |
| 265 { | 268 { |
| 266 int toret = 1; | 269 int toret = 1; |
| 267 CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); | 270 CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); |
| 268 » if(!ex_data && ((ex_data = lh_new(ex_hash_cb, ex_cmp_cb)) == NULL)) | 271 » if(!ex_data |
| 272 » && (ex_data = lh_EX_CLASS_ITEM_new()) == NULL) |
| 269 toret = 0; | 273 toret = 0; |
| 270 CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); | 274 CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); |
| 271 return toret; | 275 return toret; |
| 272 } | 276 } |
| 273 /* This macros helps reduce the locking from repeated checks because the | 277 /* This macros helps reduce the locking from repeated checks because the |
| 274 * ex_data_check() function checks ex_data again inside a lock. */ | 278 * ex_data_check() function checks ex_data again inside a lock. */ |
| 275 #define EX_DATA_CHECK(iffail) if(!ex_data && !ex_data_check()) {iffail} | 279 #define EX_DATA_CHECK(iffail) if(!ex_data && !ex_data_check()) {iffail} |
| 276 | 280 |
| 277 /* This "inner" callback is used by the callback function that follows it */ | 281 /* This "inner" callback is used by the callback function that follows it */ |
| 278 static void def_cleanup_util_cb(CRYPTO_EX_DATA_FUNCS *funcs) | 282 static void def_cleanup_util_cb(CRYPTO_EX_DATA_FUNCS *funcs) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 291 } | 295 } |
| 292 | 296 |
| 293 /* Return the EX_CLASS_ITEM from the "ex_data" hash table that corresponds to a | 297 /* Return the EX_CLASS_ITEM from the "ex_data" hash table that corresponds to a |
| 294 * given class. Handles locking. */ | 298 * given class. Handles locking. */ |
| 295 static EX_CLASS_ITEM *def_get_class(int class_index) | 299 static EX_CLASS_ITEM *def_get_class(int class_index) |
| 296 { | 300 { |
| 297 EX_CLASS_ITEM d, *p, *gen; | 301 EX_CLASS_ITEM d, *p, *gen; |
| 298 EX_DATA_CHECK(return NULL;) | 302 EX_DATA_CHECK(return NULL;) |
| 299 d.class_index = class_index; | 303 d.class_index = class_index; |
| 300 CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); | 304 CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); |
| 301 » p = lh_retrieve(ex_data, &d); | 305 » p = lh_EX_CLASS_ITEM_retrieve(ex_data, &d); |
| 302 if(!p) | 306 if(!p) |
| 303 { | 307 { |
| 304 gen = OPENSSL_malloc(sizeof(EX_CLASS_ITEM)); | 308 gen = OPENSSL_malloc(sizeof(EX_CLASS_ITEM)); |
| 305 if(gen) | 309 if(gen) |
| 306 { | 310 { |
| 307 gen->class_index = class_index; | 311 gen->class_index = class_index; |
| 308 gen->meth_num = 0; | 312 gen->meth_num = 0; |
| 309 gen->meth = sk_CRYPTO_EX_DATA_FUNCS_new_null(); | 313 gen->meth = sk_CRYPTO_EX_DATA_FUNCS_new_null(); |
| 310 if(!gen->meth) | 314 if(!gen->meth) |
| 311 OPENSSL_free(gen); | 315 OPENSSL_free(gen); |
| 312 else | 316 else |
| 313 { | 317 { |
| 314 /* Because we're inside the ex_data lock, the | 318 /* Because we're inside the ex_data lock, the |
| 315 * return value from the insert will be NULL */ | 319 * return value from the insert will be NULL */ |
| 316 » » » » lh_insert(ex_data, gen); | 320 » » » » (void)lh_EX_CLASS_ITEM_insert(ex_data, gen); |
| 317 p = gen; | 321 p = gen; |
| 318 } | 322 } |
| 319 } | 323 } |
| 320 } | 324 } |
| 321 CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); | 325 CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); |
| 322 if(!p) | 326 if(!p) |
| 323 CRYPTOerr(CRYPTO_F_DEF_GET_CLASS,ERR_R_MALLOC_FAILURE); | 327 CRYPTOerr(CRYPTO_F_DEF_GET_CLASS,ERR_R_MALLOC_FAILURE); |
| 324 return p; | 328 return p; |
| 325 } | 329 } |
| 326 | 330 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 368 int toret; | 372 int toret; |
| 369 CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); | 373 CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); |
| 370 toret = ex_class++; | 374 toret = ex_class++; |
| 371 CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); | 375 CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); |
| 372 return toret; | 376 return toret; |
| 373 } | 377 } |
| 374 | 378 |
| 375 static void int_cleanup(void) | 379 static void int_cleanup(void) |
| 376 { | 380 { |
| 377 EX_DATA_CHECK(return;) | 381 EX_DATA_CHECK(return;) |
| 378 » lh_doall(ex_data, def_cleanup_cb); | 382 » lh_EX_CLASS_ITEM_doall(ex_data, def_cleanup_cb); |
| 379 » lh_free(ex_data); | 383 » lh_EX_CLASS_ITEM_free(ex_data); |
| 380 ex_data = NULL; | 384 ex_data = NULL; |
| 381 impl = NULL; | 385 impl = NULL; |
| 382 } | 386 } |
| 383 | 387 |
| 384 static int int_get_new_index(int class_index, long argl, void *argp, | 388 static int int_get_new_index(int class_index, long argl, void *argp, |
| 385 CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, | 389 CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, |
| 386 CRYPTO_EX_free *free_func) | 390 CRYPTO_EX_free *free_func) |
| 387 { | 391 { |
| 388 EX_CLASS_ITEM *item = def_get_class(class_index); | 392 EX_CLASS_ITEM *item = def_get_class(class_index); |
| 389 if(!item) | 393 if(!item) |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 445 char *ptr; | 449 char *ptr; |
| 446 CRYPTO_EX_DATA_FUNCS **storage = NULL; | 450 CRYPTO_EX_DATA_FUNCS **storage = NULL; |
| 447 EX_CLASS_ITEM *item; | 451 EX_CLASS_ITEM *item; |
| 448 if(!from->sk) | 452 if(!from->sk) |
| 449 /* 'to' should be "blank" which *is* just like 'from' */ | 453 /* 'to' should be "blank" which *is* just like 'from' */ |
| 450 return 1; | 454 return 1; |
| 451 if((item = def_get_class(class_index)) == NULL) | 455 if((item = def_get_class(class_index)) == NULL) |
| 452 return 0; | 456 return 0; |
| 453 CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA); | 457 CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA); |
| 454 mx = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth); | 458 mx = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth); |
| 455 » j = sk_num(from->sk); | 459 » j = sk_void_num(from->sk); |
| 456 if(j < mx) | 460 if(j < mx) |
| 457 mx = j; | 461 mx = j; |
| 458 if(mx > 0) | 462 if(mx > 0) |
| 459 { | 463 { |
| 460 storage = OPENSSL_malloc(mx * sizeof(CRYPTO_EX_DATA_FUNCS*)); | 464 storage = OPENSSL_malloc(mx * sizeof(CRYPTO_EX_DATA_FUNCS*)); |
| 461 if(!storage) | 465 if(!storage) |
| 462 goto skip; | 466 goto skip; |
| 463 for(i = 0; i < mx; i++) | 467 for(i = 0; i < mx; i++) |
| 464 storage[i] = sk_CRYPTO_EX_DATA_FUNCS_value(item->meth,i)
; | 468 storage[i] = sk_CRYPTO_EX_DATA_FUNCS_value(item->meth,i)
; |
| 465 } | 469 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 { | 520 { |
| 517 ptr = CRYPTO_get_ex_data(ad,i); | 521 ptr = CRYPTO_get_ex_data(ad,i); |
| 518 storage[i]->free_func(obj,ptr,ad,i, | 522 storage[i]->free_func(obj,ptr,ad,i, |
| 519 storage[i]->argl,storage[i]->argp); | 523 storage[i]->argl,storage[i]->argp); |
| 520 } | 524 } |
| 521 } | 525 } |
| 522 if(storage) | 526 if(storage) |
| 523 OPENSSL_free(storage); | 527 OPENSSL_free(storage); |
| 524 if(ad->sk) | 528 if(ad->sk) |
| 525 { | 529 { |
| 526 » » sk_free(ad->sk); | 530 » » sk_void_free(ad->sk); |
| 527 ad->sk=NULL; | 531 ad->sk=NULL; |
| 528 } | 532 } |
| 529 } | 533 } |
| 530 | 534 |
| 531 /********************************************************************/ | 535 /********************************************************************/ |
| 532 /* API functions that defer all "state" operations to the "ex_data" | 536 /* API functions that defer all "state" operations to the "ex_data" |
| 533 * implementation we have set. */ | 537 * implementation we have set. */ |
| 534 | 538 |
| 535 /* Obtain an index for a new class (not the same as getting a new index within | 539 /* Obtain an index for a new class (not the same as getting a new index within |
| 536 * an existing class - this is actually getting a new *class*) */ | 540 * an existing class - this is actually getting a new *class*) */ |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 } | 593 } |
| 590 | 594 |
| 591 /* For a given CRYPTO_EX_DATA variable, set the value corresponding to a | 595 /* For a given CRYPTO_EX_DATA variable, set the value corresponding to a |
| 592 * particular index in the class used by this variable */ | 596 * particular index in the class used by this variable */ |
| 593 int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val) | 597 int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val) |
| 594 { | 598 { |
| 595 int i; | 599 int i; |
| 596 | 600 |
| 597 if (ad->sk == NULL) | 601 if (ad->sk == NULL) |
| 598 { | 602 { |
| 599 » » if ((ad->sk=sk_new_null()) == NULL) | 603 » » if ((ad->sk=sk_void_new_null()) == NULL) |
| 600 { | 604 { |
| 601 CRYPTOerr(CRYPTO_F_CRYPTO_SET_EX_DATA,ERR_R_MALLOC_FAILU
RE); | 605 CRYPTOerr(CRYPTO_F_CRYPTO_SET_EX_DATA,ERR_R_MALLOC_FAILU
RE); |
| 602 return(0); | 606 return(0); |
| 603 } | 607 } |
| 604 } | 608 } |
| 605 » i=sk_num(ad->sk); | 609 » i=sk_void_num(ad->sk); |
| 606 | 610 |
| 607 while (i <= idx) | 611 while (i <= idx) |
| 608 { | 612 { |
| 609 » » if (!sk_push(ad->sk,NULL)) | 613 » » if (!sk_void_push(ad->sk,NULL)) |
| 610 { | 614 { |
| 611 CRYPTOerr(CRYPTO_F_CRYPTO_SET_EX_DATA,ERR_R_MALLOC_FAILU
RE); | 615 CRYPTOerr(CRYPTO_F_CRYPTO_SET_EX_DATA,ERR_R_MALLOC_FAILU
RE); |
| 612 return(0); | 616 return(0); |
| 613 } | 617 } |
| 614 i++; | 618 i++; |
| 615 } | 619 } |
| 616 » sk_set(ad->sk,idx,val); | 620 » sk_void_set(ad->sk,idx,val); |
| 617 return(1); | 621 return(1); |
| 618 } | 622 } |
| 619 | 623 |
| 620 /* For a given CRYPTO_EX_DATA_ variable, get the value corresponding to a | 624 /* For a given CRYPTO_EX_DATA_ variable, get the value corresponding to a |
| 621 * particular index in the class used by this variable */ | 625 * particular index in the class used by this variable */ |
| 622 void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx) | 626 void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx) |
| 623 { | 627 { |
| 624 if (ad->sk == NULL) | 628 if (ad->sk == NULL) |
| 625 return(0); | 629 return(0); |
| 626 » else if (idx >= sk_num(ad->sk)) | 630 » else if (idx >= sk_void_num(ad->sk)) |
| 627 return(0); | 631 return(0); |
| 628 else | 632 else |
| 629 » » return(sk_value(ad->sk,idx)); | 633 » » return(sk_void_value(ad->sk,idx)); |
| 630 } | 634 } |
| 631 | 635 |
| 632 IMPLEMENT_STACK_OF(CRYPTO_EX_DATA_FUNCS) | 636 IMPLEMENT_STACK_OF(CRYPTO_EX_DATA_FUNCS) |
| OLD | NEW |