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/. */
7
* Error Object Functions
11
#include "pkix_error.h"
13
#undef PKIX_ERRORENTRY
15
#define PKIX_ERRORENTRY(name,desc,nsserr) #desc
17
#if defined PKIX_ERROR_DESCRIPTION
19
const char * const PKIX_ErrorText[] =
21
#include "pkix_errorstrings.h"
28
#endif /* PKIX_ERROR_DESCRIPTION */
30
extern const PKIX_Int32 PKIX_PLErrorIndex[];
32
/* --Private-Functions-------------------------------------------- */
35
* FUNCTION: pkix_Error_Equals
36
* (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
40
PKIX_PL_Object *firstObject,
41
PKIX_PL_Object *secondObject,
42
PKIX_Boolean *pResult,
45
PKIX_Error *firstError = NULL;
46
PKIX_Error *secondError = NULL;
47
PKIX_Error *firstCause = NULL;
48
PKIX_Error *secondCause = NULL;
49
PKIX_PL_Object *firstInfo = NULL;
50
PKIX_PL_Object *secondInfo = NULL;
51
PKIX_ERRORCLASS firstClass, secondClass;
52
PKIX_UInt32 secondType;
53
PKIX_Boolean boolResult, unequalFlag;
55
PKIX_ENTER(ERROR, "pkix_Error_Equals");
56
PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
58
unequalFlag = PKIX_FALSE;
60
/* First just compare pointer values to save time */
61
if (firstObject == secondObject) {
65
/* Result will only be set to true if all tests pass */
66
*pResult = PKIX_FALSE;
69
PKIX_CHECK(pkix_CheckType(firstObject, PKIX_ERROR_TYPE, plContext),
70
PKIX_FIRSTOBJECTNOTANERROROBJECT);
72
PKIX_CHECK(PKIX_PL_Object_GetType
73
(secondObject, &secondType, plContext),
74
PKIX_ERRORGETTINGSECONDOBJECTTYPE);
76
/* If types differ, then return false. Result is already set */
77
if (secondType != PKIX_ERROR_TYPE) goto cleanup;
79
/* It is safe to cast to PKIX_Error */
80
firstError = (PKIX_Error *) firstObject;
81
secondError = (PKIX_Error *) secondObject;
83
/* Compare error codes */
84
firstClass = firstError->errClass;
85
secondClass = secondError->errClass;
87
/* If codes differ, return false. Result is already set */
88
if (firstClass != secondClass) goto cleanup;
91
firstCause = firstError->cause;
92
secondCause = secondError->cause;
94
/* Ensure that either both or none of the causes are NULL */
95
if (((firstCause != NULL) && (secondCause == NULL))||
96
((firstCause == NULL) && (secondCause != NULL)))
97
unequalFlag = PKIX_TRUE;
99
if ((firstCause != NULL) && (secondCause != NULL)) {
100
PKIX_CHECK(PKIX_PL_Object_Equals
101
((PKIX_PL_Object*)firstCause,
102
(PKIX_PL_Object*)secondCause,
105
PKIX_ERRORINRECURSIVEEQUALSCALL);
107
/* Set the unequalFlag so that we return after dec refing */
108
if (boolResult == 0) unequalFlag = PKIX_TRUE;
111
/* If the cause errors are not equal, return null */
112
if (unequalFlag) goto cleanup;
114
/* Compare info fields */
115
firstInfo = firstError->info;
116
secondInfo = secondError->info;
118
if (firstInfo != secondInfo) goto cleanup;
120
/* Ensure that either both or none of the infos are NULL */
121
if (((firstInfo != NULL) && (secondInfo == NULL))||
122
((firstInfo == NULL) && (secondInfo != NULL)))
123
unequalFlag = PKIX_TRUE;
125
if ((firstInfo != NULL) && (secondInfo != NULL)) {
127
PKIX_CHECK(PKIX_PL_Object_Equals
128
((PKIX_PL_Object*)firstInfo,
129
(PKIX_PL_Object*)secondInfo,
132
PKIX_ERRORINRECURSIVEEQUALSCALL);
134
/* Set the unequalFlag so that we return after dec refing */
135
if (boolResult == 0) unequalFlag = PKIX_TRUE;
138
/* If the infos are not equal, return null */
139
if (unequalFlag) goto cleanup;
143
if (firstError->errCode != secondError->errCode) {
144
unequalFlag = PKIX_TRUE;
147
if (firstError->plErr != secondError->plErr) {
148
unequalFlag = PKIX_TRUE;
151
/* If the unequalFlag was set, return false */
152
if (unequalFlag) goto cleanup;
154
/* Errors are equal in all fields at this point */
155
*pResult = PKIX_TRUE;
163
* FUNCTION: pkix_Error_Destroy
164
* (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
168
PKIX_PL_Object *object,
171
PKIX_Error *error = NULL;
173
PKIX_ENTER(ERROR, "pkix_Error_Destroy");
174
PKIX_NULLCHECK_ONE(object);
176
PKIX_CHECK(pkix_CheckType(object, PKIX_ERROR_TYPE, plContext),
177
PKIX_OBJECTNOTANERROR);
179
error = (PKIX_Error *)object;
181
PKIX_DECREF(error->cause);
183
PKIX_DECREF(error->info);
191
/* XXX This is not thread safe */
192
static PKIX_UInt32 pkix_error_cause_depth = 1;
195
* FUNCTION: pkix_Error_ToString
196
* (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
200
PKIX_PL_Object *object,
201
PKIX_PL_String **pString,
204
PKIX_Error *error = NULL;
205
PKIX_Error *cause = NULL;
206
PKIX_PL_String *desc = NULL;
207
PKIX_PL_String *formatString = NULL;
208
PKIX_PL_String *causeString = NULL;
209
PKIX_PL_String *optCauseString = NULL;
210
PKIX_PL_String *errorNameString = NULL;
212
PKIX_ERRORCLASS errClass;
214
PKIX_ENTER(ERROR, "pkix_Error_ToString");
215
PKIX_NULLCHECK_TWO(object, pString);
217
PKIX_CHECK(pkix_CheckType(object, PKIX_ERROR_TYPE, plContext),
218
PKIX_OBJECTNOTANERROR);
220
error = (PKIX_Error *)object;
222
/* Get this error's errClass, description and the string of its cause */
223
errClass = error->errClass;
225
/* Get the description string */
226
PKIX_Error_GetDescription(error, &desc, plContext);
229
cause = error->cause;
231
/* Get the causes's description string */
233
pkix_error_cause_depth++;
235
/* Get the cause string */
236
PKIX_CHECK(PKIX_PL_Object_ToString
237
((PKIX_PL_Object*)cause, &causeString, plContext),
238
PKIX_ERRORGETTINGCAUSESTRING);
240
format = "\n*** Cause (%d): %s";
242
PKIX_CHECK(PKIX_PL_String_Create
248
PKIX_STRINGCREATEFAILED);
250
/* Create the optional Cause String */
251
PKIX_CHECK(PKIX_PL_Sprintf
255
pkix_error_cause_depth,
259
PKIX_DECREF(formatString);
261
pkix_error_cause_depth--;
264
/* Create the Format String */
265
if (optCauseString != NULL) {
266
format = "*** %s Error- %s%s";
268
format = "*** %s Error- %s";
271
/* Ensure that error errClass is known, otherwise default to Object */
272
if (errClass >= PKIX_NUMERRORCLASSES) {
276
PKIX_CHECK(PKIX_PL_String_Create
278
(void *)PKIX_ERRORCLASSNAMES[errClass],
282
PKIX_STRINGCREATEFAILED);
284
PKIX_CHECK(PKIX_PL_String_Create
290
PKIX_STRINGCREATEFAILED);
292
/* Create the output String */
293
PKIX_CHECK(PKIX_PL_Sprintf
305
PKIX_DECREF(causeString);
306
PKIX_DECREF(formatString);
307
PKIX_DECREF(optCauseString);
308
PKIX_DECREF(errorNameString);
314
* FUNCTION: pkix_Error_Hashcode
315
* (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
319
PKIX_PL_Object *object,
320
PKIX_UInt32 *pResult,
323
PKIX_ENTER(ERROR, "pkix_Error_Hashcode");
324
PKIX_NULLCHECK_TWO(object, pResult);
326
/* XXX Unimplemented */
327
/* XXX Need to make hashcodes equal when two errors are equal */
328
*pResult = (PKIX_UInt32)object;
333
/* --Initializers------------------------------------------------- */
336
* PKIX_ERRORCLASSNAMES is an array of strings, with each string holding a
337
* descriptive name for an error errClass. This is used by the default
338
* PKIX_PL_Error_ToString function.
340
* Note: PKIX_ERRORCLASSES is defined in pkixt.h as a list of error types.
341
* (More precisely, as a list of invocations of ERRMACRO(type).) The
342
* macro is expanded in pkixt.h to define error numbers, and here to
343
* provide corresponding strings. For example, since the fifth ERRMACRO
344
* entry is MUTEX, then PKIX_MUTEX_ERROR is defined in pkixt.h as 4, and
345
* PKIX_ERRORCLASSNAMES[4] is initialized here with the value "MUTEX".
348
#define ERRMACRO(type) #type
351
PKIX_ERRORCLASSNAMES[PKIX_NUMERRORCLASSES] =
357
* FUNCTION: pkix_Error_RegisterSelf
359
* Registers PKIX_ERROR_TYPE and its related functions with systemClasses[]
361
* Not Thread Safe - for performance and complexity reasons
363
* Since this function is only called by PKIX_PL_Initialize, which should
364
* only be called once, it is acceptable that this function is not
368
pkix_Error_RegisterSelf(void *plContext)
370
extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
371
pkix_ClassTable_Entry entry;
373
PKIX_ENTER(ERROR, "pkix_Error_RegisterSelf");
375
entry.description = "Error";
376
entry.objCounter = 0;
377
entry.typeObjectSize = sizeof(PKIX_Error);
378
entry.destructor = pkix_Error_Destroy;
379
entry.equalsFunction = pkix_Error_Equals;
380
entry.hashcodeFunction = pkix_Error_Hashcode;
381
entry.toStringFunction = pkix_Error_ToString;
382
entry.comparator = NULL;
383
entry.duplicateFunction = pkix_duplicateImmutable;
385
systemClasses[PKIX_ERROR_TYPE] = entry;
390
/* --Public-Functions--------------------------------------------- */
393
* FUNCTION: PKIX_Error_Create (see comments in pkix_util.h)
397
PKIX_ERRORCLASS errClass,
399
PKIX_PL_Object *info,
400
PKIX_ERRORCODE errCode,
404
PKIX_Error *tempCause = NULL;
405
PKIX_Error *error = NULL;
407
PKIX_ENTER(ERROR, "PKIX_Error_Create");
409
PKIX_NULLCHECK_ONE(pError);
412
* when called here, if PKIX_PL_Object_Alloc returns an error,
413
* it must be a PKIX_ALLOC_ERROR
415
pkixErrorResult = PKIX_PL_Object_Alloc
417
((PKIX_UInt32)(sizeof (PKIX_Error))),
418
(PKIX_PL_Object **)&error,
421
if (pkixErrorResult) return (pkixErrorResult);
423
error->errClass = errClass;
425
/* Ensure we don't have a loop. Follow causes until NULL */
426
for (tempCause = cause;
428
tempCause = tempCause->cause) {
429
/* If we detect a loop, throw a new error */
430
if (tempCause == error) {
431
PKIX_ERROR(PKIX_LOOPOFERRORCAUSEDETECTED);
436
error->cause = cause;
441
error->errCode = errCode;
443
error->plErr = PKIX_PLErrorIndex[error->errCode];
449
/* PKIX-XXX Fix for leak during error creation */
456
* FUNCTION: PKIX_Error_GetErrorClass (see comments in pkix_util.h)
459
PKIX_Error_GetErrorClass(
461
PKIX_ERRORCLASS *pClass,
464
PKIX_ENTER(ERROR, "PKIX_Error_GetErrorClass");
465
PKIX_NULLCHECK_TWO(error, pClass);
467
*pClass = error->errClass;
473
* FUNCTION: PKIX_Error_GetErrorCode (see comments in pkix_util.h)
476
PKIX_Error_GetErrorCode(
478
PKIX_ERRORCODE *pCode,
481
PKIX_ENTER(ERROR, "PKIX_Error_GetErrorCode");
482
PKIX_NULLCHECK_TWO(error, pCode);
484
*pCode = error->errCode;
490
* FUNCTION: PKIX_Error_GetCause (see comments in pkix_util.h)
498
PKIX_ENTER(ERROR, "PKIX_Error_GetCause");
499
PKIX_NULLCHECK_TWO(error, pCause);
501
if (error->cause != PKIX_ALLOC_ERROR()){
502
PKIX_INCREF(error->cause);
505
*pCause = error->cause;
512
* FUNCTION: PKIX_Error_GetSupplementaryInfo (see comments in pkix_util.h)
515
PKIX_Error_GetSupplementaryInfo(
517
PKIX_PL_Object **pInfo,
520
PKIX_ENTER(ERROR, "PKIX_Error_GetSupplementaryInfo");
521
PKIX_NULLCHECK_TWO(error, pInfo);
523
PKIX_INCREF(error->info);
525
*pInfo = error->info;
532
* FUNCTION: PKIX_Error_GetDescription (see comments in pkix_util.h)
535
PKIX_Error_GetDescription(
537
PKIX_PL_String **pDesc,
540
PKIX_PL_String *descString = NULL;
541
#ifndef PKIX_ERROR_DESCRIPTION
545
PKIX_ENTER(ERROR, "PKIX_Error_GetDescription");
546
PKIX_NULLCHECK_TWO(error, pDesc);
548
#ifndef PKIX_ERROR_DESCRIPTION
549
PR_snprintf(errorStr, 32, "Error code: %d", error->errCode);
552
PKIX_PL_String_Create(PKIX_ESCASCII,
553
#if defined PKIX_ERROR_DESCRIPTION
554
(void *)PKIX_ErrorText[error->errCode],