pkix_pl_object.c (46788B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 /* 5 * pkix_pl_object.c 6 * 7 * Object Construction, Destruction and Callback Functions 8 * 9 */ 10 11 #include "pkix_pl_object.h" 12 13 #ifdef PKIX_USER_OBJECT_TYPE 14 /* --Class-Table-Initializers------------------------------------ */ 15 16 /* 17 * Create storage space for 20 Class Table buckets. 18 * These are only for user-defined types. System types are registered 19 * separately by PKIX_PL_Initialize. 20 */ 21 22 static pkix_pl_HT_Elem* 23 pkix_Raw_ClassTable_Buckets[] = { 24 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 25 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL 26 }; 27 28 /* 29 * Allocate static memory for a ClassTable. 30 * XXX This assumes the bucket pointer will fit into a PKIX_UInt32 31 */ 32 static pkix_pl_PrimHashTable pkix_Raw_ClassTable = { 33 (void *)pkix_Raw_ClassTable_Buckets, /* Buckets */ 34 20 /* Number of Buckets */ 35 }; 36 static pkix_pl_PrimHashTable * classTable = &pkix_Raw_ClassTable; 37 #endif /* PKIX_USER_OBJECT_TYPE */ 38 39 /* --Private-Functions-------------------------------------------- */ 40 41 /* 42 * FUNCTION: pkix_pl_Object_GetHeader 43 * DESCRIPTION: 44 * 45 * Shifts Object pointed to by "object" by the sizeof(PKIX_PL_Object) and 46 * stores the value at "pObjectHeader". 47 * 48 * PARAMETERS: 49 * "object" 50 * Address of Object to shift. Must be non-NULL. 51 * "pObjectHeader" 52 * Address where object pointer will be stored. Must be non-NULL. 53 * "plContext" 54 * Platform-specific context pointer. 55 * THREAD SAFETY: 56 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 57 * RETURNS: 58 * Returns NULL if the function succeeds. 59 * Returns a Fatal Error if the function fails in an unrecoverable way. 60 */ 61 static PKIX_Error * 62 pkix_pl_Object_GetHeader( 63 PKIX_PL_Object *object, 64 PKIX_PL_Object **pObjectHeader, 65 void *plContext) 66 { 67 PKIX_PL_Object *header = NULL; 68 PKIX_UInt32 objType; 69 70 PKIX_ENTER(OBJECT, "pkix_pl_Object_GetHeader"); 71 PKIX_NULLCHECK_TWO(object, pObjectHeader); 72 73 PKIX_OBJECT_DEBUG("\tShifting object pointer).\n"); 74 75 /* The header is sizeof(PKIX_PL_Object) before the object pointer */ 76 header = (PKIX_PL_Object *)((char *)object - sizeof(PKIX_PL_Object)); 77 78 objType = header->type; 79 80 if (objType >= PKIX_NUMTYPES) { /* if this is a user-defined type */ 81 #ifdef PKIX_USER_OBJECT_TYPE 82 pkix_ClassTable_Entry *ctEntry = NULL; 83 84 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); 85 PR_Lock(classTableLock); 86 87 PKIX_CHECK(pkix_pl_PrimHashTable_Lookup 88 (classTable, 89 (void *)&objType, 90 objType, 91 NULL, 92 (void **)&ctEntry, 93 plContext), 94 PKIX_ERRORGETTINGCLASSTABLEENTRY); 95 96 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); 97 PR_Unlock(classTableLock); 98 99 if (ctEntry == NULL) { 100 PKIX_ERROR_FATAL(PKIX_UNKNOWNOBJECTTYPE); 101 } 102 #else 103 PORT_Assert(objType < PKIX_NUMTYPES); 104 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; 105 pkixErrorClass = PKIX_FATAL_ERROR; 106 goto cleanup; 107 #endif /* PKIX_USER_OBJECT_TYPE */ 108 } 109 110 #ifdef PKIX_OBJECT_LEAK_TEST 111 PORT_Assert(header && header->magicHeader == PKIX_MAGIC_HEADER); 112 #endif /* PKIX_OBJECT_LEAK_TEST */ 113 114 if ((header == NULL)|| 115 (header->magicHeader != PKIX_MAGIC_HEADER)) { 116 PKIX_ERROR_ALLOC_ERROR(); 117 } 118 119 *pObjectHeader = header; 120 121 cleanup: 122 123 PKIX_RETURN(OBJECT); 124 } 125 126 /* 127 * FUNCTION: pkix_Destroy_Object 128 * DESCRIPTION: 129 * 130 * Destroys and deallocates Object pointed to by "object". The caller is 131 * assumed to hold the Object's lock, which is acquired in 132 * PKIX_PL_Object_DecRef(). 133 * 134 * PARAMETERS: 135 * "object" 136 * Address of Object to destroy. Must be non-NULL. 137 * "plContext" 138 * Platform-specific context pointer. 139 * THREAD SAFETY: 140 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 141 * RETURNS: 142 * Returns NULL if the function succeeds. 143 * Returns a Fatal Error if the function fails in an unrecoverable way. 144 */ 145 static PKIX_Error * 146 pkix_pl_Object_Destroy( 147 PKIX_PL_Object *object, 148 void *plContext) 149 { 150 PKIX_PL_Object *objectHeader = NULL; 151 152 PKIX_ENTER(OBJECT, "pkix_pl_Object_Destroy"); 153 PKIX_NULLCHECK_ONE(object); 154 155 #ifdef PKIX_OBJECT_LEAK_TEST 156 PKIX_CHECK_FATAL(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), 157 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); 158 #else 159 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), 160 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); 161 #endif /* PKIX_OBJECT_LEAK_TEST */ 162 163 /* Attempt to delete an object still being used */ 164 if (objectHeader->references != 0) { 165 PKIX_ERROR_FATAL(PKIX_OBJECTSTILLREFERENCED); 166 } 167 168 PKIX_DECREF(objectHeader->stringRep); 169 170 /* Destroy this object's lock */ 171 PKIX_OBJECT_DEBUG("\tCalling PR_DestroyLock).\n"); 172 PR_DestroyLock(objectHeader->lock); 173 objectHeader->lock = NULL; 174 object = NULL; 175 176 objectHeader->magicHeader = PKIX_MAGIC_HEADER_DESTROYED; 177 178 #ifdef PKIX_OBJECT_LEAK_TEST 179 memset(objectHeader, 0xbf, systemClasses[PKIX_OBJECT_TYPE].typeObjectSize); 180 #endif 181 182 PKIX_FREE(objectHeader); 183 184 cleanup: 185 #ifdef PKIX_OBJECT_LEAK_TEST 186 fatal: 187 #endif 188 189 PKIX_RETURN(OBJECT); 190 } 191 192 /* --Default-Callbacks-------------------------------------------- */ 193 194 /* 195 * FUNCTION: pkix_pl_Object_Equals_Default 196 * DESCRIPTION: 197 * 198 * Default Object_Equals callback: Compares the address of the Object pointed 199 * to by "firstObject" with the address of the Object pointed to by 200 * "secondObject" and stores the Boolean result at "pResult". 201 * 202 * PARAMETERS: 203 * "firstObject" 204 * Address of first Object to compare. Must be non-NULL. 205 * "secondObject" 206 * Address of second Object to compare. Must be non-NULL. 207 * "pResult" 208 * Address where Boolean result will be stored. Must be non-NULL. 209 * "plContext" 210 * Platform-specific context pointer. 211 * THREAD SAFETY: 212 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 213 * RETURNS: 214 * Returns NULL if the function succeeds. 215 * Returns a Fatal Error if the function fails in an unrecoverable way. 216 */ 217 static PKIX_Error * 218 pkix_pl_Object_Equals_Default( 219 PKIX_PL_Object *firstObject, 220 PKIX_PL_Object *secondObject, 221 PKIX_Boolean *pResult, 222 void *plContext) 223 { 224 PKIX_ENTER(OBJECT, "pkix_pl_Object_Equals_Default"); 225 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); 226 227 /* Just compare pointer values */ 228 *pResult = (firstObject == secondObject)?PKIX_TRUE:PKIX_FALSE; 229 230 PKIX_RETURN(OBJECT); 231 } 232 233 /* 234 * FUNCTION: pkix_pl_Object_ToString_Default 235 * DESCRIPTION: 236 * 237 * Default Object_ToString callback: Creates a string consisting of the 238 * typename and address of the Object pointed to by "object" and stores 239 * the result at "pString". The format for the string is 240 * "TypeName@Address: <address>", where the default typename is "Object". 241 * 242 * PARAMETERS: 243 * "object" 244 * Address of Object to convert to a string. Must be non-NULL. 245 * "pString" 246 * Address where object pointer will be stored. Must be non-NULL. 247 * "plContext" 248 * Platform-specific context pointer. 249 * THREAD SAFETY: 250 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 251 * RETURNS: 252 * Returns NULL if the function succeeds. 253 * Returns an Object Error if the function fails in a non-fatal way. 254 * Returns a Fatal Error if the function fails in an unrecoverable way. 255 */ 256 static PKIX_Error * 257 pkix_pl_Object_ToString_Default( 258 PKIX_PL_Object *object, 259 PKIX_PL_String **pString, 260 void *plContext) 261 { 262 PKIX_PL_String *formatString = NULL; 263 PKIX_PL_String *descString = NULL; 264 char *format = "%s@Address: %x"; 265 char *description = NULL; 266 PKIX_UInt32 objType; 267 268 PKIX_ENTER(OBJECT, "pkix_pl_Object_ToString_Default"); 269 PKIX_NULLCHECK_TWO(object, pString); 270 271 PKIX_CHECK(PKIX_PL_Object_GetType(object, &objType, plContext), 272 PKIX_OBJECTGETTYPEFAILED); 273 274 if (objType >= PKIX_NUMTYPES){ 275 #ifdef PKIX_USER_OBJECT_TYPE 276 pkix_ClassTable_Entry *ctEntry = NULL; 277 278 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); 279 PR_Lock(classTableLock); 280 pkixErrorResult = pkix_pl_PrimHashTable_Lookup 281 (classTable, 282 (void *)&objType, 283 objType, 284 NULL, 285 (void **)&ctEntry, 286 plContext); 287 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); 288 PR_Unlock(classTableLock); 289 if (pkixErrorResult){ 290 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY); 291 } 292 293 if (ctEntry == NULL){ 294 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCLASSTABLEENTRY); 295 } else { 296 description = ctEntry->description; 297 if (description == NULL) { 298 description = "User Type Object"; 299 } 300 } 301 #else 302 PORT_Assert (0); 303 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; 304 pkixErrorClass = PKIX_FATAL_ERROR; 305 goto cleanup; 306 #endif /* PKIX_USER_OBJECT_TYPE */ 307 } else { 308 description = systemClasses[objType].description; 309 } 310 PKIX_CHECK(PKIX_PL_String_Create 311 (PKIX_ESCASCII, 312 (void *)format, 313 0, 314 &formatString, 315 plContext), 316 PKIX_STRINGCREATEFAILED); 317 318 PKIX_CHECK(PKIX_PL_String_Create 319 (PKIX_ESCASCII, 320 (void *)description, 321 0, 322 &descString, 323 plContext), 324 PKIX_STRINGCREATEFAILED); 325 326 PKIX_CHECK(PKIX_PL_Sprintf 327 (pString, 328 plContext, 329 formatString, 330 descString, 331 object), 332 PKIX_SPRINTFFAILED); 333 334 cleanup: 335 336 PKIX_DECREF(formatString); 337 PKIX_DECREF(descString); 338 339 PKIX_RETURN(OBJECT); 340 } 341 342 /* 343 * FUNCTION: pkix_pl_Object_Hashcode_Default 344 * DESCRIPTION: 345 * 346 * Default Object_Hashcode callback. Creates the a hashcode value using the 347 * address of the Object pointed to by "object" and stores the result at 348 * "pValue". 349 * 350 * XXX This isn't great since addresses are not uniformly distributed. 351 * 352 * PARAMETERS: 353 * "object" 354 * Address of Object to compute hashcode for. Must be non-NULL. 355 * "pValue" 356 * Address where PKIX_UInt32 will be stored. Must be non-NULL. 357 * "plContext" 358 * Platform-specific context pointer. 359 * THREAD SAFETY: 360 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 361 * RETURNS: 362 * Returns NULL if the function succeeds. 363 * Returns a Fatal Error if the function fails in an unrecoverable way. 364 */ 365 static PKIX_Error * 366 pkix_pl_Object_Hashcode_Default( 367 PKIX_PL_Object *object, 368 PKIX_UInt32 *pValue, 369 void *plContext) 370 { 371 PKIX_ENTER(OBJECT, "pkix_pl_Object_Hashcode_Default"); 372 PKIX_NULLCHECK_TWO(object, pValue); 373 374 *pValue = (PKIX_UInt32)((char *)object - (char *)NULL); 375 376 PKIX_RETURN(OBJECT); 377 } 378 379 /* 380 * FUNCTION: pkix_pl_Object_RetrieveEqualsCallback 381 * DESCRIPTION: 382 * 383 * Retrieves Equals callback function of Object pointed to by "object and 384 * stores it at "pEqualsCallback". If the object's type is one of the system 385 * types, its callback function is retrieved from the systemClasses array; 386 * otherwise, its callback function is retrieve from the classTable hash 387 * table where user-defined types are stored. 388 * 389 * PARAMETERS: 390 * "object" 391 * Address of Object whose equals callback is desired. Must be non-NULL. 392 * "pEqualsCallback" 393 * Address where EqualsCallback function pointer will be stored. 394 * Must be non-NULL. 395 * "plContext" 396 * Platform-specific context pointer. 397 * THREAD SAFETY: 398 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 399 * RETURNS: 400 * Returns NULL if the function succeeds. 401 * Returns an Object Error if the function fails in a non-fatal way. 402 * Returns a Fatal Error if the function fails in an unrecoverable way. 403 */ 404 PKIX_Error * 405 pkix_pl_Object_RetrieveEqualsCallback( 406 PKIX_PL_Object *object, 407 PKIX_PL_EqualsCallback *pEqualsCallback, 408 void *plContext) 409 { 410 PKIX_PL_Object *objectHeader = NULL; 411 PKIX_PL_EqualsCallback func = NULL; 412 pkix_ClassTable_Entry entry; 413 PKIX_UInt32 objType; 414 415 PKIX_ENTER(OBJECT, "pkix_pl_Object_RetrieveEqualsCallback"); 416 PKIX_NULLCHECK_TWO(object, pEqualsCallback); 417 418 PKIX_CHECK(pkix_pl_Object_GetHeader 419 (object, &objectHeader, plContext), 420 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); 421 422 objType = objectHeader->type; 423 424 if (objType >= PKIX_NUMTYPES){ 425 #ifdef PKIX_USER_OBJECT_TYPE 426 pkix_ClassTable_Entry *ctEntry = NULL; 427 428 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); 429 PR_Lock(classTableLock); 430 pkixErrorResult = pkix_pl_PrimHashTable_Lookup 431 (classTable, 432 (void *)&objType, 433 objType, 434 NULL, 435 (void **)&ctEntry, 436 plContext); 437 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); 438 PR_Unlock(classTableLock); 439 if (pkixErrorResult){ 440 PKIX_ERROR(PKIX_ERRORGETTINGCLASSTABLEENTRY); 441 } 442 443 if ((ctEntry == NULL) || (ctEntry->equalsFunction == NULL)) { 444 PKIX_ERROR(PKIX_UNDEFINEDEQUALSCALLBACK); 445 } else { 446 *pEqualsCallback = ctEntry->equalsFunction; 447 } 448 #else 449 PORT_Assert (0); 450 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; 451 pkixErrorClass = PKIX_FATAL_ERROR; 452 goto cleanup; 453 #endif /* PKIX_USER_OBJECT_TYPE */ 454 } else { 455 entry = systemClasses[objType]; 456 func = entry.equalsFunction; 457 if (func == NULL){ 458 func = pkix_pl_Object_Equals_Default; 459 } 460 *pEqualsCallback = func; 461 } 462 463 cleanup: 464 465 PKIX_RETURN(OBJECT); 466 } 467 468 /* 469 * FUNCTION: pkix_pl_Object_RegisterSelf 470 * DESCRIPTION: 471 * Registers PKIX_OBJECT_TYPE and its related functions with systemClasses[] 472 * THREAD SAFETY: 473 * Not Thread Safe - for performance and complexity reasons 474 * 475 * Since this function is only called by PKIX_PL_Initialize, which should 476 * only be called once, it is acceptable that this function is not 477 * thread-safe. 478 * 479 * PKIX_PL_Object should have all function pointes to be to NULL: they 480 * work as proxy function to a real objects. 481 * 482 */ 483 PKIX_Error * 484 pkix_pl_Object_RegisterSelf(void *plContext) 485 { 486 pkix_ClassTable_Entry entry; 487 488 PKIX_ENTER(ERROR, "pkix_pl_Object_RegisterSelf"); 489 490 entry.description = "Object"; 491 entry.objCounter = 0; 492 entry.typeObjectSize = sizeof(PKIX_PL_Object); 493 entry.destructor = NULL; 494 entry.equalsFunction = NULL; 495 entry.hashcodeFunction = NULL; 496 entry.toStringFunction = NULL; 497 entry.comparator = NULL; 498 entry.duplicateFunction = NULL; 499 500 systemClasses[PKIX_OBJECT_TYPE] = entry; 501 502 PKIX_RETURN(ERROR); 503 } 504 505 /* --Public-Functions------------------------------------------------------- */ 506 507 /* 508 * FUNCTION: PKIX_PL_Object_Alloc (see comments in pkix_pl_system.h) 509 */ 510 PKIX_Error * 511 PKIX_PL_Object_Alloc( 512 PKIX_TYPENUM objType, 513 PKIX_UInt32 size, 514 PKIX_PL_Object **pObject, 515 void *plContext) 516 { 517 PKIX_PL_Object *object = NULL; 518 pkix_ClassTable_Entry *ctEntry = NULL; 519 520 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Alloc"); 521 PKIX_NULLCHECK_ONE(pObject); 522 523 /* 524 * We need to ensure that user-defined types have been registered. 525 * All system types have already been registered by PKIX_PL_Initialize. 526 */ 527 528 if (objType >= PKIX_NUMTYPES) { /* i.e. if this is a user-defined type */ 529 #ifdef PKIX_USER_OBJECT_TYPE 530 PKIX_Boolean typeRegistered; 531 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); 532 PR_Lock(classTableLock); 533 pkixErrorResult = pkix_pl_PrimHashTable_Lookup 534 (classTable, 535 (void *)&objType, 536 objType, 537 NULL, 538 (void **)&ctEntry, 539 plContext); 540 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); 541 PR_Unlock(classTableLock); 542 if (pkixErrorResult){ 543 PKIX_ERROR_FATAL(PKIX_COULDNOTLOOKUPINHASHTABLE); 544 } 545 546 typeRegistered = (ctEntry != NULL); 547 548 if (!typeRegistered) { 549 PKIX_ERROR_FATAL(PKIX_UNKNOWNTYPEARGUMENT); 550 } 551 #else 552 PORT_Assert (0); 553 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; 554 pkixErrorClass = PKIX_FATAL_ERROR; 555 goto cleanup; 556 #endif /* PKIX_USER_OBJECT_TYPE */ 557 } else { 558 ctEntry = &systemClasses[objType]; 559 } 560 561 PORT_Assert(size == ctEntry->typeObjectSize); 562 563 /* Allocate space for the object header and the requested size */ 564 #ifdef PKIX_OBJECT_LEAK_TEST 565 PKIX_CHECK(PKIX_PL_Calloc 566 (1, 567 ((PKIX_UInt32)sizeof (PKIX_PL_Object))+size, 568 (void **)&object, 569 plContext), 570 PKIX_MALLOCFAILED); 571 #else 572 PKIX_CHECK(PKIX_PL_Malloc 573 (((PKIX_UInt32)sizeof (PKIX_PL_Object))+size, 574 (void **)&object, 575 plContext), 576 PKIX_MALLOCFAILED); 577 #endif /* PKIX_OBJECT_LEAK_TEST */ 578 579 /* Initialize all object fields */ 580 object->magicHeader = PKIX_MAGIC_HEADER; 581 object->type = objType; 582 object->references = 1; /* Default to a single reference */ 583 object->stringRep = NULL; 584 object->hashcode = 0; 585 object->hashcodeCached = 0; 586 587 /* Cannot use PKIX_PL_Mutex because it depends on Object */ 588 /* Using NSPR Locks instead */ 589 PKIX_OBJECT_DEBUG("\tCalling PR_NewLock).\n"); 590 object->lock = PR_NewLock(); 591 if (object->lock == NULL) { 592 PKIX_ERROR_ALLOC_ERROR(); 593 } 594 595 PKIX_OBJECT_DEBUG("\tShifting object pointer).\n"); 596 597 598 /* Return a pointer to the user data. Need to offset by object size */ 599 *pObject = object + 1; 600 object = NULL; 601 602 /* Atomically increment object counter */ 603 PR_ATOMIC_INCREMENT((PRInt32*)&ctEntry->objCounter); 604 605 cleanup: 606 607 PKIX_FREE(object); 608 609 PKIX_RETURN(OBJECT); 610 } 611 612 /* 613 * FUNCTION: PKIX_PL_Object_IsTypeRegistered (see comments in pkix_pl_system.h) 614 */ 615 PKIX_Error * 616 PKIX_PL_Object_IsTypeRegistered( 617 PKIX_UInt32 objType, 618 PKIX_Boolean *pBool, 619 void *plContext) 620 { 621 #ifdef PKIX_USER_OBJECT_TYPE 622 pkix_ClassTable_Entry *ctEntry = NULL; 623 #endif 624 625 PKIX_ENTER(OBJECT, "PKIX_PL_Object_IsTypeRegistered"); 626 PKIX_NULLCHECK_ONE(pBool); 627 628 /* first, we handle the system types */ 629 if (objType < PKIX_NUMTYPES) { 630 *pBool = PKIX_TRUE; 631 goto cleanup; 632 } 633 634 #ifndef PKIX_USER_OBJECT_TYPE 635 PORT_Assert (0); 636 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; 637 pkixErrorClass = PKIX_FATAL_ERROR; 638 #else 639 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); 640 PR_Lock(classTableLock); 641 pkixErrorResult = pkix_pl_PrimHashTable_Lookup 642 (classTable, 643 (void *)&objType, 644 objType, 645 NULL, 646 (void **)&ctEntry, 647 plContext); 648 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); 649 PR_Unlock(classTableLock); 650 651 if (pkixErrorResult){ 652 PKIX_ERROR_FATAL(PKIX_COULDNOTLOOKUPINHASHTABLE); 653 } 654 655 *pBool = (ctEntry != NULL); 656 #endif /* PKIX_USER_OBJECT_TYPE */ 657 658 cleanup: 659 660 PKIX_RETURN(OBJECT); 661 } 662 663 #ifdef PKIX_USER_OBJECT_TYPE 664 /* 665 * FUNCTION: PKIX_PL_Object_RegisterType (see comments in pkix_pl_system.h) 666 */ 667 PKIX_Error * 668 PKIX_PL_Object_RegisterType( 669 PKIX_UInt32 objType, 670 char *description, 671 PKIX_PL_DestructorCallback destructor, 672 PKIX_PL_EqualsCallback equalsFunction, 673 PKIX_PL_HashcodeCallback hashcodeFunction, 674 PKIX_PL_ToStringCallback toStringFunction, 675 PKIX_PL_ComparatorCallback comparator, 676 PKIX_PL_DuplicateCallback duplicateFunction, 677 void *plContext) 678 { 679 pkix_ClassTable_Entry *ctEntry = NULL; 680 pkix_pl_Integer *key = NULL; 681 682 PKIX_ENTER(OBJECT, "PKIX_PL_Object_RegisterType"); 683 684 /* 685 * System types are registered on startup by PKIX_PL_Initialize. 686 * These can not be overwritten. 687 */ 688 689 if (objType < PKIX_NUMTYPES) { /* if this is a system type */ 690 PKIX_ERROR(PKIX_CANTREREGISTERSYSTEMTYPE); 691 } 692 693 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); 694 PR_Lock(classTableLock); 695 PKIX_CHECK(pkix_pl_PrimHashTable_Lookup 696 (classTable, 697 (void *)&objType, 698 objType, 699 NULL, 700 (void **)&ctEntry, 701 plContext), 702 PKIX_PRIMHASHTABLELOOKUPFAILED); 703 704 /* If the type is already registered, throw an error */ 705 if (ctEntry) { 706 PKIX_ERROR(PKIX_TYPEALREADYREGISTERED); 707 } 708 709 PKIX_CHECK(PKIX_PL_Malloc 710 (((PKIX_UInt32)sizeof (pkix_ClassTable_Entry)), 711 (void **)&ctEntry, 712 plContext), 713 PKIX_MALLOCFAILED); 714 715 /* Set Default Values if none specified */ 716 717 if (description == NULL){ 718 description = "Object"; 719 } 720 721 if (equalsFunction == NULL) { 722 equalsFunction = pkix_pl_Object_Equals_Default; 723 } 724 725 if (toStringFunction == NULL) { 726 toStringFunction = pkix_pl_Object_ToString_Default; 727 } 728 729 if (hashcodeFunction == NULL) { 730 hashcodeFunction = pkix_pl_Object_Hashcode_Default; 731 } 732 733 ctEntry->destructor = destructor; 734 ctEntry->equalsFunction = equalsFunction; 735 ctEntry->toStringFunction = toStringFunction; 736 ctEntry->hashcodeFunction = hashcodeFunction; 737 ctEntry->comparator = comparator; 738 ctEntry->duplicateFunction = duplicateFunction; 739 ctEntry->description = description; 740 741 PKIX_CHECK(PKIX_PL_Malloc 742 (((PKIX_UInt32)sizeof (pkix_pl_Integer)), 743 (void **)&key, 744 plContext), 745 PKIX_COULDNOTMALLOCNEWKEY); 746 747 key->ht_int = objType; 748 749 PKIX_CHECK(pkix_pl_PrimHashTable_Add 750 (classTable, 751 (void *)key, 752 (void *)ctEntry, 753 objType, 754 NULL, 755 plContext), 756 PKIX_PRIMHASHTABLEADDFAILED); 757 758 cleanup: 759 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); 760 PR_Unlock(classTableLock); 761 762 PKIX_RETURN(OBJECT); 763 } 764 #endif /* PKIX_USER_OBJECT_TYPE */ 765 766 /* 767 * FUNCTION: PKIX_PL_Object_IncRef (see comments in pkix_pl_system.h) 768 */ 769 PKIX_Error * 770 PKIX_PL_Object_IncRef( 771 PKIX_PL_Object *object, 772 void *plContext) 773 { 774 PKIX_PL_Object *objectHeader = NULL; 775 PKIX_PL_NssContext *context = NULL; 776 PKIX_Int32 refCount = 0; 777 778 PKIX_ENTER(OBJECT, "PKIX_PL_Object_IncRef"); 779 PKIX_NULLCHECK_ONE(object); 780 781 if (plContext){ 782 /* 783 * PKIX_PL_NssContext is not a complete PKIX Type, it doesn't 784 * have a header therefore we cannot verify its type before 785 * casting. 786 */ 787 context = (PKIX_PL_NssContext *) plContext; 788 if (context->arena != NULL) { 789 goto cleanup; 790 } 791 } 792 793 if (object == (PKIX_PL_Object*)PKIX_ALLOC_ERROR()) { 794 goto cleanup; 795 } 796 797 /* Shift pointer from user data to object header */ 798 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), 799 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); 800 801 /* This object should never have zero references */ 802 refCount = PR_ATOMIC_INCREMENT(&objectHeader->references); 803 804 if (refCount <= 1) { 805 PKIX_THROW(FATAL, PKIX_OBJECTWITHNONPOSITIVEREFERENCES); 806 } 807 808 cleanup: 809 810 PKIX_RETURN(OBJECT); 811 } 812 813 /* 814 * FUNCTION: PKIX_PL_Object_DecRef (see comments in pkix_pl_system.h) 815 */ 816 PKIX_Error * 817 PKIX_PL_Object_DecRef( 818 PKIX_PL_Object *object, 819 void *plContext) 820 { 821 PKIX_Int32 refCount = 0; 822 PKIX_PL_Object *objectHeader = NULL; 823 PKIX_PL_NssContext *context = NULL; 824 825 PKIX_ENTER(OBJECT, "PKIX_PL_Object_DecRef"); 826 PKIX_NULLCHECK_ONE(object); 827 828 if (plContext){ 829 /* 830 * PKIX_PL_NssContext is not a complete PKIX Type, it doesn't 831 * have a header therefore we cannot verify its type before 832 * casting. 833 */ 834 context = (PKIX_PL_NssContext *) plContext; 835 if (context->arena != NULL) { 836 goto cleanup; 837 } 838 } 839 840 if (object == (PKIX_PL_Object*)PKIX_ALLOC_ERROR()) { 841 goto cleanup; 842 } 843 844 /* Shift pointer from user data to object header */ 845 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), 846 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); 847 848 refCount = PR_ATOMIC_DECREMENT(&objectHeader->references); 849 850 if (refCount == 0) { 851 PKIX_PL_DestructorCallback destructor = NULL; 852 pkix_ClassTable_Entry *ctEntry = NULL; 853 PKIX_UInt32 objType = objectHeader->type; 854 855 /* first, special handling for system types */ 856 if (objType >= PKIX_NUMTYPES){ 857 #ifdef PKIX_USER_OBJECT_TYPE 858 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); 859 PR_Lock(classTableLock); 860 pkixErrorResult = pkix_pl_PrimHashTable_Lookup 861 (classTable, 862 (void *)&objType, 863 objType, 864 NULL, 865 (void **)&ctEntry, 866 plContext); 867 PKIX_OBJECT_DEBUG 868 ("\tCalling PR_Unlock).\n"); 869 PR_Unlock(classTableLock); 870 if (pkixErrorResult){ 871 PKIX_ERROR_FATAL 872 (PKIX_ERRORINGETTINGDESTRUCTOR); 873 } 874 875 if (ctEntry != NULL){ 876 destructor = ctEntry->destructor; 877 } 878 #else 879 PORT_Assert (0); 880 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; 881 pkixErrorClass = PKIX_FATAL_ERROR; 882 goto cleanup; 883 #endif /* PKIX_USER_OBJECT_TYPE */ 884 } else { 885 ctEntry = &systemClasses[objType]; 886 destructor = ctEntry->destructor; 887 } 888 889 if (destructor != NULL){ 890 /* Call destructor on user data if necessary */ 891 pkixErrorResult = destructor(object, plContext); 892 if (pkixErrorResult) { 893 pkixErrorClass = PKIX_FATAL_ERROR; 894 PKIX_DoAddError(stdVarsPtr, pkixErrorResult, plContext); 895 pkixErrorResult = NULL; 896 } 897 } 898 899 /* Atomically decrement object counter */ 900 PR_ATOMIC_DECREMENT((PRInt32*)&ctEntry->objCounter); 901 902 /* pkix_pl_Object_Destroy assumes the lock is held */ 903 /* It will call unlock and destroy the object */ 904 pkixErrorResult = pkix_pl_Object_Destroy(object, plContext); 905 goto cleanup; 906 } 907 908 if (refCount < 0) { 909 PKIX_ERROR_ALLOC_ERROR(); 910 } 911 912 cleanup: 913 914 PKIX_RETURN(OBJECT); 915 } 916 917 918 919 /* 920 * FUNCTION: PKIX_PL_Object_Equals (see comments in pkix_pl_system.h) 921 */ 922 PKIX_Error * 923 PKIX_PL_Object_Equals( 924 PKIX_PL_Object *firstObject, 925 PKIX_PL_Object *secondObject, 926 PKIX_Boolean *pResult, 927 void *plContext) 928 { 929 PKIX_PL_Object *firstObjectHeader = NULL; 930 PKIX_PL_Object *secondObjectHeader = NULL; 931 PKIX_PL_EqualsCallback func = NULL; 932 pkix_ClassTable_Entry entry; 933 PKIX_UInt32 objType; 934 935 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Equals"); 936 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); 937 938 PKIX_CHECK(pkix_pl_Object_GetHeader 939 (firstObject, &firstObjectHeader, plContext), 940 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); 941 942 PKIX_CHECK(pkix_pl_Object_GetHeader 943 (secondObject, &secondObjectHeader, plContext), 944 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); 945 946 /* if hashcodes are cached but not equal, objects can't be equal */ 947 if (firstObjectHeader->hashcodeCached && 948 secondObjectHeader->hashcodeCached){ 949 if (firstObjectHeader->hashcode != 950 secondObjectHeader->hashcode){ 951 *pResult = PKIX_FALSE; 952 goto cleanup; 953 } 954 } 955 956 objType = firstObjectHeader->type; 957 958 if (objType >= PKIX_NUMTYPES) { 959 #ifdef PKIX_USER_OBJECT_TYPE 960 pkix_ClassTable_Entry *ctEntry = NULL; 961 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); 962 PR_Lock(classTableLock); 963 pkixErrorResult = pkix_pl_PrimHashTable_Lookup 964 (classTable, 965 (void *)&firstObjectHeader->type, 966 firstObjectHeader->type, 967 NULL, 968 (void **)&ctEntry, 969 plContext); 970 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); 971 PR_Unlock(classTableLock); 972 973 if (pkixErrorResult){ 974 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY); 975 } 976 977 if ((ctEntry == NULL) || (ctEntry->equalsFunction == NULL)) { 978 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK); 979 } else { 980 func = ctEntry->equalsFunction; 981 } 982 #else 983 PORT_Assert (0); 984 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; 985 pkixErrorClass = PKIX_FATAL_ERROR; 986 goto cleanup; 987 #endif /* PKIX_USER_OBJECT_TYPE */ 988 } else { 989 entry = systemClasses[objType]; 990 func = entry.equalsFunction; 991 if (func == NULL){ 992 func = pkix_pl_Object_Equals_Default; 993 } 994 } 995 996 PKIX_CHECK(func(firstObject, secondObject, pResult, plContext), 997 PKIX_OBJECTSPECIFICFUNCTIONFAILED); 998 999 cleanup: 1000 1001 PKIX_RETURN(OBJECT); 1002 } 1003 1004 /* 1005 * FUNCTION: PKIX_PL_Object_Duplicate (see comments in pkix_pl_system.h) 1006 */ 1007 PKIX_Error * 1008 PKIX_PL_Object_Duplicate( 1009 PKIX_PL_Object *firstObject, 1010 PKIX_PL_Object **pNewObject, 1011 void *plContext) 1012 { 1013 PKIX_PL_Object *firstObjectHeader = NULL; 1014 PKIX_PL_DuplicateCallback func = NULL; 1015 pkix_ClassTable_Entry entry; 1016 PKIX_UInt32 objType; 1017 1018 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Duplicate"); 1019 PKIX_NULLCHECK_TWO(firstObject, pNewObject); 1020 1021 PKIX_CHECK(pkix_pl_Object_GetHeader 1022 (firstObject, &firstObjectHeader, plContext), 1023 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); 1024 1025 objType = firstObjectHeader->type; 1026 1027 if (objType >= PKIX_NUMTYPES) { 1028 #ifdef PKIX_USER_OBJECT_TYPE 1029 pkix_ClassTable_Entry *ctEntry = NULL; 1030 1031 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); 1032 PR_Lock(classTableLock); 1033 pkixErrorResult = pkix_pl_PrimHashTable_Lookup 1034 (classTable, 1035 (void *)&objType, 1036 objType, 1037 NULL, 1038 (void **)&ctEntry, 1039 plContext); 1040 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); 1041 PR_Unlock(classTableLock); 1042 1043 if (pkixErrorResult){ 1044 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY); 1045 } 1046 1047 if ((ctEntry == NULL) || (ctEntry->duplicateFunction == NULL)) { 1048 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK); 1049 } else { 1050 func = ctEntry->duplicateFunction; 1051 } 1052 #else 1053 PORT_Assert (0); 1054 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; 1055 pkixErrorClass = PKIX_FATAL_ERROR; 1056 goto cleanup; 1057 #endif /* PKIX_USER_OBJECT_TYPE */ 1058 } else { 1059 entry = systemClasses[objType]; 1060 func = entry.duplicateFunction; 1061 if (!func){ 1062 PKIX_ERROR_FATAL(PKIX_UNDEFINEDDUPLICATEFUNCTION); 1063 } 1064 } 1065 1066 PKIX_CHECK(func(firstObject, pNewObject, plContext), 1067 PKIX_OBJECTSPECIFICFUNCTIONFAILED); 1068 1069 cleanup: 1070 1071 PKIX_RETURN(OBJECT); 1072 } 1073 1074 /* 1075 * FUNCTION: PKIX_PL_Object_Hashcode (see comments in pkix_pl_system.h) 1076 */ 1077 PKIX_Error * 1078 PKIX_PL_Object_Hashcode( 1079 PKIX_PL_Object *object, 1080 PKIX_UInt32 *pValue, 1081 void *plContext) 1082 { 1083 PKIX_PL_Object *objectHeader = NULL; 1084 PKIX_PL_HashcodeCallback func = NULL; 1085 pkix_ClassTable_Entry entry; 1086 PKIX_UInt32 objectHash; 1087 1088 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Hashcode"); 1089 PKIX_NULLCHECK_TWO(object, pValue); 1090 1091 /* Shift pointer from user data to object header */ 1092 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), 1093 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); 1094 1095 /* if we don't have a cached copy from before, we create one */ 1096 if (!objectHeader->hashcodeCached){ 1097 1098 PKIX_UInt32 objType = objectHeader->type; 1099 1100 /* first, special handling for system types */ 1101 if (objType >= PKIX_NUMTYPES){ 1102 #ifdef PKIX_USER_OBJECT_TYPE 1103 pkix_ClassTable_Entry *ctEntry = NULL; 1104 1105 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); 1106 PR_Lock(classTableLock); 1107 pkixErrorResult = pkix_pl_PrimHashTable_Lookup 1108 (classTable, 1109 (void *)&objType, 1110 objType, 1111 NULL, 1112 (void **)&ctEntry, 1113 plContext); 1114 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); 1115 PR_Unlock(classTableLock); 1116 1117 if (pkixErrorResult){ 1118 PKIX_ERROR_FATAL 1119 (PKIX_ERRORGETTINGCLASSTABLEENTRY); 1120 } 1121 1122 if ((ctEntry == NULL) || 1123 (ctEntry->hashcodeFunction == NULL)) { 1124 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK); 1125 } 1126 1127 func = ctEntry->hashcodeFunction; 1128 #else 1129 PORT_Assert (0); 1130 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; 1131 pkixErrorClass = PKIX_FATAL_ERROR; 1132 goto cleanup; 1133 #endif /* PKIX_USER_OBJECT_TYPE */ 1134 } else { 1135 entry = systemClasses[objType]; 1136 func = entry.hashcodeFunction; 1137 if (func == NULL){ 1138 func = pkix_pl_Object_Hashcode_Default; 1139 } 1140 } 1141 1142 PKIX_CHECK(func(object, &objectHash, plContext), 1143 PKIX_OBJECTSPECIFICFUNCTIONFAILED); 1144 1145 if (!objectHeader->hashcodeCached){ 1146 1147 PKIX_CHECK(pkix_LockObject(object, plContext), 1148 PKIX_ERRORLOCKINGOBJECT); 1149 1150 if (!objectHeader->hashcodeCached){ 1151 /* save cached copy in case we need it again */ 1152 objectHeader->hashcode = objectHash; 1153 objectHeader->hashcodeCached = PKIX_TRUE; 1154 } 1155 1156 PKIX_CHECK(pkix_UnlockObject(object, plContext), 1157 PKIX_ERRORUNLOCKINGOBJECT); 1158 } 1159 } 1160 1161 *pValue = objectHeader->hashcode; 1162 1163 cleanup: 1164 1165 PKIX_RETURN(OBJECT); 1166 } 1167 1168 /* 1169 * FUNCTION: PKIX_PL_Object_ToString (see comments in pkix_pl_system.h) 1170 */ 1171 PKIX_Error * 1172 PKIX_PL_Object_ToString( 1173 PKIX_PL_Object *object, 1174 PKIX_PL_String **pString, 1175 void *plContext) 1176 { 1177 PKIX_PL_Object *objectHeader = NULL; 1178 PKIX_PL_ToStringCallback func = NULL; 1179 pkix_ClassTable_Entry entry; 1180 PKIX_PL_String *objectString = NULL; 1181 1182 PKIX_ENTER(OBJECT, "PKIX_PL_Object_ToString"); 1183 PKIX_NULLCHECK_TWO(object, pString); 1184 1185 /* Shift pointer from user data to object header */ 1186 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), 1187 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); 1188 1189 /* if we don't have a cached copy from before, we create one */ 1190 if (!objectHeader->stringRep){ 1191 1192 PKIX_UInt32 objType = objectHeader->type; 1193 1194 if (objType >= PKIX_NUMTYPES){ 1195 #ifdef PKIX_USER_OBJECT_TYPE 1196 pkix_ClassTable_Entry *ctEntry = NULL; 1197 1198 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); 1199 PR_Lock(classTableLock); 1200 pkixErrorResult = pkix_pl_PrimHashTable_Lookup 1201 (classTable, 1202 (void *)&objType, 1203 objType, 1204 NULL, 1205 (void **)&ctEntry, 1206 plContext); 1207 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); 1208 PR_Unlock(classTableLock); 1209 if (pkixErrorResult){ 1210 PKIX_ERROR_FATAL 1211 (PKIX_ERRORGETTINGCLASSTABLEENTRY); 1212 } 1213 1214 if ((ctEntry == NULL) || 1215 (ctEntry->toStringFunction == NULL)) { 1216 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK); 1217 } 1218 1219 func = ctEntry->toStringFunction; 1220 #else 1221 PORT_Assert (0); 1222 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; 1223 pkixErrorClass = PKIX_FATAL_ERROR; 1224 goto cleanup; 1225 #endif /* PKIX_USER_OBJECT_TYPE */ 1226 } else { 1227 entry = systemClasses[objType]; 1228 func = entry.toStringFunction; 1229 if (func == NULL){ 1230 func = pkix_pl_Object_ToString_Default; 1231 } 1232 } 1233 1234 PKIX_CHECK(func(object, &objectString, plContext), 1235 PKIX_OBJECTSPECIFICFUNCTIONFAILED); 1236 1237 if (!objectHeader->stringRep){ 1238 1239 PKIX_CHECK(pkix_LockObject(object, plContext), 1240 PKIX_ERRORLOCKINGOBJECT); 1241 1242 if (!objectHeader->stringRep){ 1243 /* save a cached copy */ 1244 objectHeader->stringRep = objectString; 1245 objectString = NULL; 1246 } 1247 1248 PKIX_CHECK(pkix_UnlockObject(object, plContext), 1249 PKIX_ERRORUNLOCKINGOBJECT); 1250 } 1251 } 1252 1253 1254 *pString = objectHeader->stringRep; 1255 objectHeader->stringRep = NULL; 1256 1257 cleanup: 1258 if (objectHeader) { 1259 PKIX_DECREF(objectHeader->stringRep); 1260 } 1261 PKIX_DECREF(objectString); 1262 1263 PKIX_RETURN(OBJECT); 1264 } 1265 1266 /* 1267 * FUNCTION: PKIX_PL_Object_InvalidateCache (see comments in pkix_pl_system.h) 1268 */ 1269 PKIX_Error * 1270 PKIX_PL_Object_InvalidateCache( 1271 PKIX_PL_Object *object, 1272 void *plContext) 1273 { 1274 PKIX_PL_Object *objectHeader = NULL; 1275 1276 PKIX_ENTER(OBJECT, "PKIX_PL_Object_InvalidateCache"); 1277 PKIX_NULLCHECK_ONE(object); 1278 1279 /* Shift pointer from user data to object header */ 1280 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), 1281 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); 1282 1283 PKIX_CHECK(pkix_LockObject(object, plContext), 1284 PKIX_ERRORLOCKINGOBJECT); 1285 1286 /* invalidate hashcode */ 1287 objectHeader->hashcode = 0; 1288 objectHeader->hashcodeCached = PKIX_FALSE; 1289 1290 PKIX_DECREF(objectHeader->stringRep); 1291 1292 PKIX_CHECK(pkix_UnlockObject(object, plContext), 1293 PKIX_ERRORUNLOCKINGOBJECT); 1294 1295 cleanup: 1296 1297 PKIX_RETURN(OBJECT); 1298 } 1299 1300 /* 1301 * FUNCTION: PKIX_PL_Object_Compare (see comments in pkix_pl_system.h) 1302 */ 1303 PKIX_Error * 1304 PKIX_PL_Object_Compare( 1305 PKIX_PL_Object *firstObject, 1306 PKIX_PL_Object *secondObject, 1307 PKIX_Int32 *pResult, 1308 void *plContext) 1309 { 1310 PKIX_PL_Object *firstObjectHeader = NULL; 1311 PKIX_PL_Object *secondObjectHeader = NULL; 1312 PKIX_PL_ComparatorCallback func = NULL; 1313 pkix_ClassTable_Entry entry; 1314 PKIX_UInt32 objType; 1315 1316 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Compare"); 1317 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); 1318 1319 /* Shift pointer from user data to object header */ 1320 PKIX_CHECK(pkix_pl_Object_GetHeader 1321 (firstObject, &firstObjectHeader, plContext), 1322 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); 1323 1324 /* Shift pointer from user data to object header */ 1325 PKIX_CHECK(pkix_pl_Object_GetHeader 1326 (secondObject, &secondObjectHeader, plContext), 1327 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); 1328 1329 objType = firstObjectHeader->type; 1330 1331 if (objType >= PKIX_NUMTYPES){ 1332 #ifdef PKIX_USER_OBJECT_TYPE 1333 pkix_ClassTable_Entry *ctEntry = NULL; 1334 1335 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); 1336 PR_Lock(classTableLock); 1337 pkixErrorResult = pkix_pl_PrimHashTable_Lookup 1338 (classTable, 1339 (void *)&objType, 1340 objType, 1341 NULL, 1342 (void **)&ctEntry, 1343 plContext); 1344 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); 1345 PR_Unlock(classTableLock); 1346 if (pkixErrorResult){ 1347 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY); 1348 } 1349 1350 if ((ctEntry == NULL) || (ctEntry->comparator == NULL)) { 1351 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCOMPARATOR); 1352 } 1353 1354 func = ctEntry->comparator; 1355 #else 1356 PORT_Assert (0); 1357 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; 1358 pkixErrorClass = PKIX_FATAL_ERROR; 1359 goto cleanup; 1360 #endif /* PKIX_USER_OBJECT_TYPE */ 1361 } else { 1362 /* special handling for system types */ 1363 entry = systemClasses[objType]; 1364 func = entry.comparator; 1365 if (!func){ 1366 PKIX_ERROR(PKIX_UNDEFINEDCOMPARATOR); 1367 } 1368 } 1369 1370 PKIX_CHECK(func(firstObject, secondObject, pResult, plContext), 1371 PKIX_OBJECTSPECIFICFUNCTIONFAILED); 1372 1373 cleanup: 1374 1375 PKIX_RETURN(OBJECT); 1376 } 1377 1378 /* 1379 * FUNCTION: PKIX_PL_Object_Lock (see comments in pkix_pl_system.h) 1380 */ 1381 PKIX_Error * 1382 PKIX_PL_Object_Lock( 1383 PKIX_PL_Object *object, 1384 void *plContext) 1385 { 1386 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Lock"); 1387 PKIX_NULLCHECK_ONE(object); 1388 1389 PKIX_CHECK(pkix_LockObject(object, plContext), 1390 PKIX_LOCKOBJECTFAILED); 1391 1392 cleanup: 1393 1394 PKIX_RETURN(OBJECT); 1395 } 1396 1397 /* 1398 * FUNCTION: PKIX_PL_Object_Unlock (see comments in pkix_pl_system.h) 1399 */ 1400 PKIX_Error * 1401 PKIX_PL_Object_Unlock( 1402 PKIX_PL_Object *object, 1403 void *plContext) 1404 { 1405 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Unlock"); 1406 PKIX_NULLCHECK_ONE(object); 1407 1408 PKIX_CHECK(pkix_UnlockObject(object, plContext), 1409 PKIX_UNLOCKOBJECTFAILED); 1410 1411 cleanup: 1412 1413 PKIX_RETURN(OBJECT); 1414 } 1415 1416 1417 /* 1418 * FUNCTION: PKIX_PL_Object_GetType (see comments in pkix_pl_system.h) 1419 */ 1420 PKIX_Error * 1421 PKIX_PL_Object_GetType( 1422 PKIX_PL_Object *object, 1423 PKIX_UInt32 *pType, 1424 void *plContext) 1425 { 1426 PKIX_PL_Object *objectHeader = NULL; 1427 1428 PKIX_ENTER(OBJECT, "PKIX_PL_Object_GetType"); 1429 PKIX_NULLCHECK_TWO(object, pType); 1430 1431 /* Shift pointer from user data to object header */ 1432 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), 1433 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); 1434 1435 *pType = objectHeader->type; 1436 1437 cleanup: 1438 1439 PKIX_RETURN(OBJECT); 1440 }